본문 바로가기
코딩이야기/트러블슈팅

[React] 뒤로가기 막는 방법 (feat.모달창)

by TaeHyeon0412 2024. 6. 11.

문제 상황

모달을 열고 닫은 뒤 뒤로가기 버튼을 누르면 이전 URL로 넘어 가면서 모달창이 다시 열리는 현상이 발생했습니다.

 

뒤로가기 클릭시 모달창이 다시 나오는 현상

 

 

이 현상을 해결하기 위해 useEffect를 사용하여 뒤로가기를 누를때 동작을 정의해주는 함수를 만들어 주었습니다.
홈페이지 전체에서 뒤로가기를 막아야 되기 때문에 App.js에 추가해 주었습니다.

 

1
2
3
4
5
6
7
8
9
10
11
function App() {
  useEffect(() => {
    const preventGoBack = () => {
      window.history.go(1);
      console.log("prevent go back!");
    };
    window.history.pushState(null""window.location.pathname);
    window.addEventListener("popstate", preventGoBack);
    return () => window.removeEventListener("popstate", preventGoBack);
  }, []);
  //뒤로가기 막기
cs

 

코드 해석

동작원리 : useEffect를 사용하여 브라우저의 뒤로가기 버튼을 감지하고 , 감지되면 브라우저의 페이지 이동을 제어 하는 방법입니다.


useEffect => 컴포넌트가 렌더링(마운트) 될 때 한 번 실행되며, 뒤로 가기 버튼의 동작을 감지하는 리스너를 등록합니다.


preventGoBack => 뒤로가기 버튼을 눌렀을때 실행되는 함수로, 뒤로가기 버튼을 누르면 window.history.go(1)를 
호출하여 브라우저의 히스토리를 한 단계 앞으로 이동시킵니다. (1은 앞으로 -1은 뒤로)


window.history.pushState(null, " ", window.location.pathname) => 뒤로가기 버튼을 눌렀을때 페이지 이동을 감지하고pushState 를 이용해서 URL을 현재 페이지의 경로를 추가하는 것입니다.
pushState 메서드의 3개의 인수 = (상태, 제목,URL) // window.location.pathname = 현재 페이지간단하게 말해서 현재 페이지의 URL을 히스토리 스택에 추가하는 역할을 합니다.

window.addEventListener("popstate", preventGoBack) => popstate 이벤트 감지, preventGoBack 함수 실행


return ( ) => window.removeEventListener("popstate", preventGoBack) => 컴포넌트가 언마운트될 때 이벤트 리스너를 정리합니다.


이벤트 리스너를 정리하는 이유 : 메모리 누수를 방지하고 불필요한 이벤트 핸들링을 중지하는데 도움이 되기 때문!

 

 

하지만 이렇게 하면 모달창이 열리고 난 뒤에도 뒤로가기 버튼이 안눌리는 현상이 발생합니다.

 

왜 모달창을 뒤로가기 버튼으로 닫으려고 하나요? : 모바일 환경에서는 뒤로가기 버튼으로 모달창을 닫는 경우가 많아서 

그 부분도 신경 써야 될 것 같아서입니다.

 

 

모달창도 뒤로가기가 안먹는 현상

 

 

모달창은 뒤로가기 버튼으로 닫을 수 있게 만들고 모달창을 닫은 뒤에는 뒤로가기 버튼으로 모달창이 

안 나오게 하기 위해 useEffect를 이용하여 모달창 자체에 다시 함수를 만들어 주었습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
useEffect(() => {
    const goBackHome = () => {
      navigate(`/`, { replace: true });
      console.log("모달창 뒤로가기 => 홈");
    };
 
    window.history.pushState(null""window.location.pathname);
    window.addEventListener("popstate", goBackHome);
 
    return () => window.removeEventListener("popstate", goBackHome);
  }, [navigate]);
cs

 

 

코드 해석

동작 원리 : 모달이 열렸을 때, 사용자가 브라우저의 뒤로가기 버튼을 누르면 홈 화면으로 돌아가도록 하는 코드입니다.


useEffect => 컴포넌트가 렌더링 될 때 한 번 실행되며, 뒤로 가기 버튼의 동작을 감지하는 리스너를 등록합니다.


goBackHome => 브라우저의 뒤로가기 버튼을 누를 때 실행될 함수입니다. 이 함수 내에서는 navigate 함수를 사용하여 홈 화면으로 이동하도록 설정합니다. 
{ replace: true } : 현재 페이지를 새로운 페이지로 교체합니다. 새로운 페이지로 이동하면서 이전 페이지를 브라우저의 히스토리 스택에 추가하지 않습니다.


window.history.pushState(null, "", window.location.pathname)=> 첫번째 코드와 같은 코드입니다. 뒤로가기 버튼을 눌렀을때 페이지 이동을 감지하고pushState 를 이용해서 URL을 현재 페이지의 경로를 추가하는 것입니다.


window.addEventListener("popstate", goBackHome) => popstate 이벤트 감지, goBackHome 함수 실행


return () => window.removeEventListener("popstate", goBackHome) => 컴포넌트가 언마운트될 때 이벤트 리스너를 정리합니다.

 

이 코드는 모달 컴포넌트 부분에 적용시켜 주었습니다.

 

 

결과 : 

 

해결!

 

 

모달창은 뒤로가기로 닫을 수 있고 모달창을 닫은 뒤에는 뒤로가기 버튼을 눌러도 모달창이 다시 안 나오게 되었습니다. 

console.log를 보면 렌더링이 2번씩 되는 현상이 있는데 이건 조금 더 생각을 해봐야 될 것 같습니다

 

해결 완료!