nextjs에서 브라우저 뒤로가기 및 새로고침 방지하기

Doori Kim
5 min readOct 7, 2021

--

What I wanted

  • 사용자가 새로고침을 했을 때 커스텀 팝업을 띄우기
  • 사용자가 브라우저 뒤로가기 버튼을 눌렀을 때 커스텀 팝업 띄우기

Did

새로고침 감지하기

새로고침의 경우, 아래와 같이 event listener에 beforeunload 이벤트를 걸어주면 된다.

const handleReload = (e) => {  e.preventDefault();  e.returnValue = ""}useEffect(() => {
if (조건) {
window.addEventListener('beforeunload', handleReload);
}
return () => { window.removeEventListener('beforeunload', handleReload); }}, [변수])

나는 화면단에서 파일 업로드를 해놓은 상태에서 새로고침을 할 경우에만 팝업을 띄워야했기 때문에 effect의 dependency에 파일명을 넣었다.

이 코드로 목표의 절반은 성공하고 절반은 실패했다. 왜냐, 목표는 커스텀 팝업을 띄우는 것 이었지만, 최신 브라우저에서는 기본 팝업창을 가릴수도 없고, 문구를 커스텀하는 것도 불가능하다. 하지만 익스플로러에서는 문구 수정도 가능하다고 하다!

세상엔 선량한 개발자들만 있는 것이 아니기 때문에 보안상의 이슈로 최신 브라우저에선 문구수정을 막아놓은 것 같다. 예를 들어

“계속할 경우 당신의 계좌에서 금일백만원이 빠져나갑니다.”

이런 식으로 글자가 쓰여있다면 괜히 사이트 잘못 들어왔다가 겁나서 나가지 못하는 사람들이 생길수도 있고 뭐… 사기꾼들이 언제나 문제다!!!

어쨌든 새로고침의 경우 커스텀 팝업을 적용할 수 없습니다~

뒤로가기

프로젝트에 커스텀 뒤로가기 버튼이 있어서 거기에 이벤트를 걸어놓았지만, 사용자는 브라우저에 어디든 누를 수 있기 때문에! 열심히 검색검색… 구글링을 하다 하다 온 동네 글씨를 보랏빛으로 물들일 시점 쯤에.. 스택오버플로우에서 이 글을 발견했다!

새로고침과 마찬가지로 window eventlistener를 통해 이벤트를 걸어주는 건줄 알았는데 nextjs의 router를 통해 이벤트를 걸어주는 것이었다.

준비물

  • route가 변경될 때 커스텀 팝업을 띄워주기 위해 popup을 띄울지 결정하는 state
  • 커스텀 팝업에서 확인버튼을 눌렀을 때, 원래 이동하려던 route로 이동해주기 위한 state -> routeChangeStart에 걸리는 함수의 첫번째 인자를 저장
const handleRouteChange = (url) => {  setIsLeavingPopup(true)  setDestination(url);  throw `Route change to "${pathname}" was aborted (this error can be safely ignored).`;}const leavePage = () => {  setIsLeavingPopup(false);  setIsLeavingClicked(true);}useEffect(() => {  if (!fileName) return; // 파일이 업로드되지 않은 상태에선 자유롭게 뒤로가도됨  router.events.on('routeChangeStart', handleRouteChange);  if (isLeavingClicked) {    setIsLeavingClicked(false);    router.replace(destination);    router.events.off('routeChangeStart', handleRouteChange);  }  return () => {    router.events.off('routeChangeStart', handleRouteChange);  }}, [pathname, fileName, isLeavingClicked])

위의 시도를 하면 이렇게 콘솔창에 가짜 error가 뜨면서 페이지 이동을 막아준다. routeChangeStart 자체가 페이지 이동을 감지하지만, 에러로 돌려막기를 해주지 않으면 페이지 이동을 해버리기 때문에! 페이지 이동 전에 특정 행위를 하려면 무조건 에러를 걸어줘야 하는 것 같다..

이 방법 말고도 react-router-dom에서 useBlocker를 쓰면 엄청 커다란 팝업창이 하나 뜨던데 실제로 써보지 않아서 커스텀이 가능한진 모르겠다!

어찌됐든… 내가 본 스택오버플로우 글에선 routeChangeErrorthrow 를 함께 써서 둘을 무조건 세트로 써야하는줄 알았는데 그게 아니였다! 위의 코드처럼 걍 throw를 하면 된다.

문제 발견

BreadCrumb이나 커스텀 뒤로가기 등.. 인위적으로 프로젝트에 박아놓은 버튼을 눌렀을 때는 상관이 없다.

하지만, 브라우저의 뒤로가기를 누를 경우 페이지 이동도 하기도 전에 주소가 이동할 주소로 바뀌어버린다! 이 상태에서 새로고침을 하면 바로 그 페이지로 이동이 되어버리는 이슈가 있다.

뒤로가기 눌렀을 때 주소 바뀌는 건 내가 제어할 수 없는 부분인 것 같고, 커스텀 팝업에서 취소 눌렀을 때 다시 원래 주소로 바뀌도록 적용해놓았다 하하..

Thoughts

  • 정말 별별 이벤트와 동작들을 제어할 수 있구나. 프론트앤드는 파도파도 끝이 없구나.
  • 블로그 오랜만이라 글 쓰는거 어색하다. 앞으론 자주 쓰자.

--

--