서비스의 필요성
북스테어즈(https://book-stairs.com/) 서비스 작업을 하다가
뒤로 가기 막기 / 창 닫기 막기 / 새로고침 막기의 기능이 요구되었다
우리가 글 작성 등의 작업을 하며
실수로 뒤로 가기, 새로고침, 창 닫기를 한다고 생각해보자
정말 끔찍하다!
이에 대해 네이버 블로그같은 경우에는, 아래 사진과 같이 경고창을 띄우며 막는다
우리 서비스에도 독서를 하며 질문과 답변을 직접 작성하는 기능이 주이기 때문에,
위와 같은 기능이 꼭 필요할 것 같다
하나씩 해보도록 하자
창 닫기 및 새로고침 막기
창이 닫히거나, 새로고침을 할 경우에 window 객체는 beforeunload 이벤트를 발생시킨다
beforeunload 는 문서나 그 리소스가 unload 되기 직전에 window에서 발생한다
그리고 이는 Cancelable(취소 가능) 하여
e.preventDefault() 메소드로 창이 닫히거나 새로고침 등을 취소할 수 있다
https://developer.mozilla.org/ko/docs/Web/API/Window/beforeunload_event
공식 문서의 예제에도 나와있듯이,
간단하게 구현이 가능하다
window.addEventListener('beforeunload', (event) => {
// 표준에 따라 기본 동작 방지
event.preventDefault();
// Chrome에서는 returnValue 설정이 필요함
event.returnValue = '';
});
그리고 위 코드를 React에 적용을 시키기 위해,
useEffect에 작성하였다
const preventClose = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue = ""; //Chrome에서 동작하도록; deprecated
};
useEffect(() => {
(() => {
window.addEventListener("beforeunload", preventClose);
})();
return () => {
window.removeEventListener("beforeunload", preventClose);
};
}, []);
이벤트 객체의 returnValue 는 deprecated 된 속성이지만, 일단 넣어줬다
https://developer.mozilla.org/en-US/docs/Web/API/Event/returnValue
또한 useEffect에서 위 코드와 같이 콜백함수로 감싸주어야,
보다 더 명확한 동작이 이루어진다고 한다
https://ko.reactjs.org/docs/hooks-effect.html
같은 방법으로, 뒤로 가기 동작도 막아보도록 하자
뒤로 가기 막기
뒤로 가기를 할 때에는 popstate 이벤트가 발생한다
이는 사용자가 세션 기록 탐색을 하여, 현재 활성화된 기록 항목이 바뀔 때 발생한다
https://developer.mozilla.org/ko/docs/Web/API/Window/popstate_event
popstate 이벤트가 beforeunload 이벤트와 다른 점은 Cancelable 하지 않다는 점이다
이 이유로 e.preventDefault() 메소드로 동작을 막을 수는 없다
공식 문서에도 언급된, history.pushState(state, title[, url]) 메서드를 활용한다
https://developer.mozilla.org/ko/docs/Web/API/History/pushState
아래 코드를 보자
history.pushState(null, "", location.href);
window.addEventListener("popstate", () => history.pushState(null, "", location.href));
우선, 브라우저의 세션 기록 스택에 상태를 추가한다
이 상태는 현재 페이지의 상태 그대로이므로 복사본을 저장하는 꼴이다
그리고 window 객체에 popstate 이벤트 리스터를 추가한다
그 때에도 history.pushState() 메소드를 불러옴으로써 복사본을 저장한다
그렇게 되면 우리가 뒤로 가기를 눌러도, 현재 상태를 유지하게 되고,
하나를 또 복사하였으므로 다음 뒤로 가기도 안 눌리게 된다
이를 React에 적용을 시키기 위해,
useEffect에 작성하면 다음과 같다
const preventGoBack = () => {
history.pushState(null, "", location.href);
};
useEffect(() => {
history.pushState(null, "", location.href);
window.addEventListener("popstate", preventGoBack);
return () => {
window.removeEventListener("popstate", preventGoBack);
handleCloseDrawer();
};
}, []);
나아갈 점
window 객체의 조작을 React에 적용하였다
그래서 어떠한 상태(state)에 따라 달리 처리하고 싶었다
예를 들어, 글이 변경되어야 뒤로 가기를 막는다던지?
그러나 이를 구현할 때 문제였던 점은
페이지를 렌더링 하는 시점에서부터 history.pushState() 메소드를 호출한다는 것이다
이렇게 되면, 글이 변경되지 않았을 때 뒤로 가기를 2번 눌러서야 뒤로 가기가 동작한다
이 부분에 대해서는 조금 더 생각을 해봐야 할 것 같다 🧐🧐
'Web.d' 카테고리의 다른 글
[React][Webpack] webpack, babel 로 시작하기 (without CRA) (0) | 2022.03.20 |
---|---|
[React][css] 마우스 hover 시에 svg 보이기 (0) | 2022.03.13 |
[React][비교] SWR vs React Query vs Recoil selector ? (0) | 2022.02.18 |
[React][framer-motion] framer-motion Animation Library (0) | 2022.02.08 |
[React] map 함수에 key 값이 필요한 이유 (재조정; Reconciliation) (0) | 2022.02.02 |