문제 상황
모달을 열고 닫은 뒤 뒤로가기 버튼을 누르면 이전 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번씩 되는 현상이 있는데 이건 조금 더 생각을 해봐야 될 것 같습니다
해결 완료!
'코딩이야기 > 트러블슈팅' 카테고리의 다른 글
[React] Input 컴포넌트에서 useRef 오류가 날 때 (0) | 2024.09.09 |
---|---|
[Next.js] build시 정적 페이지 생성 오류 (0) | 2024.09.06 |
[Next.js] sharp 라이브러리 적용 후 vercel 배포 시 런타임 오류 발생 (4) | 2024.07.13 |
[React] scrollTo 스크롤 이벤트 오류 (찔끔찔끔 올라가는 버그) (1) | 2024.06.11 |
[Next.js] build할 때 checkFields<Diff<LayoutProps, FirstArg<TEntry['default']>, 'default'>>() 오류 기록 (0) | 2024.04.18 |