Next.js에서 Route 및 페이지 이탈 방지하기

Next.js에서 useRouter를 활용해 사용자가 특정 조건에서 페이지를 떠나는 것을 방지하는 방법을 설명합니다.
Next.jshooks
avatar
2024.12.29
·
5 min read

해당 아티클은 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;

주요 기능 및 동작 방식

  1. Route 변경 감지

    • Next.js의 router.events를 활용하여 routeChangeStart 이벤트를 구독합니다.

    • 새로운 URL이 현재 URL과 다른 경우, onBlock 콜백을 실행하여 사용자가 수행 중인 작업을 멈출 수 있는 기회를 제공합니다.

  2. 페이지 이탈 방지

    • 브라우저의 beforeunload 이벤트를 등록하여 사용자가 페이지를 떠날 때 브라우저 기본 경고를 표시하거나 동작을 막을 수 있습니다.

  3. 해제 기능 제공

    • 훅이 반환하는 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 훅은 사용자 작업 중 발생할 수 있는 실수나 의도치 않은 이탈을 방지하는 데 유용합니다. 이를 통해 중요한 데이터를 보호하고 사용자 경험을 개선할 수 있습니다.

더 나은 개선 아이디어가 있거나 추가 기능이 필요하다면 언제든 의견을 나눠주세요!







- 컬렉션 아티클