모달이나 바텀시트 컴포넌트는 사용자의 주의를 환기시키거나 또는 중요한 정보를 전달해야 할 때 매우 유용하게 사용됩니다.
그런데 사용자가 해당 창을 닫기 위해 웹 브라우저의 뒤로가기 동작을 수행하게 되면 이전 페이지로 되돌아가버리게 됩니다.
이는 결국 사용성을 해치는 것이 되는데요, 모달이 띄워져 있을 때 웹 브라우저 자체의 뒤로가기를 했을 때 이전 페이지로 이동되지 않고 열려 있는 모달창(또는 바텀시트나 팝업 등)을 닫으려면 아래와 같이 구현하면 됩니다.
본 포스팅에서는 모달을 예시로 설명하고 있으나 모달 뿐만이 아니라 어떤 컴포넌트라도 응용이 가능합니다.
모달 컴포넌트와 이를 열어주는 버튼은 이미 구현했다고 가정하겠습니다.
let isModalOpen = false;
// 모달 띄우기
function handleOpenModal() {
isModalOpen = true;
document.querySelector('.modal').classList.add('show');
history.pushState({ isModalOpen: true }, '');
}
// 모달 닫기
function handleCloseModal() {
isModalOpen = false;
document.querySelector('.modal').classList.remove('show');
history.replaceState({ isModalOpen: false }, '');
}
// 브라우저의 히스토리 변경이 일어날 시 실행될 코드
window.onpopstate = function (event) {
if ( isModalOpen ) {
// 모달이 띄워져 있으면 모달을 닫습니다.
handleCloseModal();
} else {
// 모달이 띄워져 있지 않다면 이전 페이지로 이동합니다.
history.go(-1);
}
}
history.pushState
history.pushState() 메서드는 브라우저에 새로운 히스토리 엔트리를 생성합니다.
history.pushState(state, unused, url);
state
상태를 관리하는 객체로, pushState()에 의해 새로운 히스토리 엔트리가 추가되었을 때, popstate
이벤트가 발생합니다.
이 때 popstate
의 state
속성은 히스토리 엔트리 상태의 복사본을 담게 됩니다.
state
객체에는 직렬화가 가능한 모든 형태의 데이터를 지정할 수 있습니다.
unused
현재는 사용되지 않는 인자이며, 빈 값으로 지정하면 됩니다.
url
새로운 히스토리 엔트리의 URL입니다. 여기에는 절대경로와 상대경로 모두 지정해줄 수 있으며 상대경로일 경우, 현재 페이지의 동일한 origin을 가지고 있어야 합니다.
history.replaceState
history.replaceState() 메서드는 새로운 히스토리 엔트리를 추가하지 않고, 현재의 엔트리를 새로운 엔트리로 덮어씌웁니다.
history.replaceState(state, unused, url);
인자는 history.pushState() 메서드와 마찬가지로 동일한 3가지를 제공하며, 역할 또한 비슷합니다.
window.onpopstate
window 객체의 onpopstate
이벤트는 웹 브라우저의 뒤로가기/앞으로가기 동작으로 인해 현재 히스토리 엔트리에 변화가 생길 때 발생하게 됩니다.
예를 들어, 사용자가 뒤로가기 버튼을 누르게 되면 popstate
이벤트가 발생하고 event.state
를 통해서 해당 상태 객체에 접근할 수 있습니다.
window.onpopstate = function (event) {
// event.state에는 pushState 또는 replaceState에서 전달한 상태 객체가 들어있습니다.
const state = event.state;
// 여기서 상태에 따른 동작을 수행할 수 있습니다.
};
이와 같이 window.onpopstate
, history.pushState
, history.replaceState
를 이용해서 매우 간단하게 상태 값에 따른 뒤로가기 제어가 가능합니다.
'웹개발 > JavaScript' 카테고리의 다른 글
로컬스토리지(LocalStorage)에 객체(Object) 저장하기 (0) | 2024.01.18 |
---|