Next.js에서 Route 및 페이지 이탈 방지하기
해당 아티클은 next.js의 pages router를 기준으로 작성되었습니다.
이탈 방지 훅의 필요성
사용자가 중요한 데이터를 입력하거나 작업을 진행 중일 때, 페이지를 실수로 떠나거나 이동하면 불편함을 초래할 수 있습니다. 이를 방지하기 위해 페이지 이탈 시 사용자에게 경고를 표시하거나 특정 작업을 수행할 수 있는 기능을 구현하는 경우들이 존재합니다.
이 글에서는 Next.js에서 useRouter
와 브라우저의 beforeunload
이벤트를 활용해 route 및 페이지 이탈을 방지하는 useBlockRouteChange
훅을 만들어보겠습니다.
훅 설계 및 구현
아래는 이탈 방지 훅 useBlockRouteChange
의 구현 코드입니다. 이 훅은 사용자가 페이지를 떠나려고 할 때 특정 동작을 실행하거나 이탈을 막을 수 있도록 설계되었습니다.
import { useRouter } from 'next/router';
import { useCallback, useEffect } from 'react';
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
e.preventDefault();
};
const useBlockRouteChange = (onBlock: (blockedUrl: string) => void) => {
const router = useRouter();
const handleRouteChangeStart = useCallback(
(url: string) => {
if (decodeURIComponent(url).includes(decodeURIComponent(router.asPath))) {
return;
}
if (router.asPath !== window.location.pathname) {
window.history.pushState(null, '', router.asPath);
}
onBlock(url);
router.events.emit('routeChangeError');
throw new Error('routeChangeError');
},
[router, onBlock],
);
useEffect(() => {
router.events.on('routeChangeStart', handleRouteChangeStart);
window.addEventListener('beforeunload', handleBeforeUnload);
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart);
window.removeEventListener('beforeunload', handleBeforeUnload);
};
}, [router.events, handleRouteChangeStart]);
const unblockRoute = () => {
router.events.off('routeChangeStart', handleRouteChangeStart);
window.removeEventListener('beforeunload', handleBeforeUnload);
};
return unblockRoute;
};
export default useBlockRouteChange;
주요 기능 및 동작 방식
Route 변경 감지
Next.js의
router.events
를 활용하여routeChangeStart
이벤트를 구독합니다.새로운 URL이 현재 URL과 다른 경우,
onBlock
콜백을 실행하여 사용자가 수행 중인 작업을 멈출 수 있는 기회를 제공합니다.
페이지 이탈 방지
브라우저의
beforeunload
이벤트를 등록하여 사용자가 페이지를 떠날 때 브라우저 기본 경고를 표시하거나 동작을 막을 수 있습니다.
해제 기능 제공
훅이 반환하는
unblockRoute
를 호출하면 페이지 이탈 방지 동작을 해제할 수 있습니다. 이로써 상황에 따라 동작을 유연하게 제어할 수 있습니다.
활용 방법
아래는 useBlockRouteChange
훅을 실제로 사용하는 예제입니다.
import { useState } from 'react';
import useBlockRouteChange from './useBlockRouteChange';
const MyComponent = () => {
const [isBlocking, setIsBlocking] = useState(true);
const unblockRoute = useBlockRouteChange((blockedUrl) => {
if (isBlocking) {
alert(`페이지를 떠나시겠습니까?`);
}
});
return (
<div>
<p>여기에서 페이지 이탈 방지 로직을 테스트할 수 있습니다.</p>
<button onClick={() => setIsBlocking(false)}>이탈 방지 해제</button>
<button onClick={unblockRoute}>훅 동작 해제</button>
</div>
);
};
export default MyComponent;
결론
useBlockRouteChange
훅은 사용자 작업 중 발생할 수 있는 실수나 의도치 않은 이탈을 방지하는 데 유용합니다. 이를 통해 중요한 데이터를 보호하고 사용자 경험을 개선할 수 있습니다.
더 나은 개선 아이디어가 있거나 추가 기능이 필요하다면 언제든 의견을 나눠주세요!