거짓말쟁이 검거
오늘은 SPA을 만들 때 활용되는 History API의 사용법에 대해 알게되었다.
일반적으로 앞으로/뒤로 가기 버튼을 누르거나 동일한 역할을 하는 코드(history.back()
history.forward()
) 실행 시 발생하는 이벤트라고 볼 수 있다.
구체적으로 어떤 때 발생하느냐는 조금 복잡하게 느껴졌다.
mdn에 따르면 navigate 하거나 세션 스토리지를 traverse 하는 과정에서 세션 히스토리에 새 entry의 state로 History.state가 변화될 때 발생한다고 한다.
첫 번째 참조의 사이트에 의하면 현재 페이지와 같은 document 객체를 공유하는 페이지로 navigate할 때, 쉽게 말하면 페이지 리로드 없이 navigate할 때 발생한다고 한다.
두 가지를 결합해서 이해하려니까 너무 어려워서 일단 우리가 사용하려는 목적에 맞게 결과론적인 설명으로 작성했다.
중요한 것은 History API 중 pushState
나 replaceState
호출만으로는 발생하지 않는다.
chatGPT조차 잘못된 설명을 내놓는 사항이다.
예전에 react 과제 리뷰하다가 이런게 있다더라 정도만 알아보고 넘어갔던 적이 있다.
Vanilla JS로 SPA을 구현하려면 필수적으로 활용해야하는 것 같으니 정리해두려고 한다.
History API는 history
전역 객체를 통해 브라우저의 세션 히스토리에 접근하는 방법을 제시한다.
세션 히스토리는 스택 방식으로 유저의 브라우징 문맥이 변경될 때마다 새로운 entry
가 쌓이게 된다.
브라우징 문맥이 변경되는 상황은 4종류 정도가 존재한다.
location.href
, window.location
같은 자바스크립트 메서드를 사용하는 경우를 말한다.하지만 위 세 가지 모두 기본 동작이 서버에 해당 url의 index.html을 요청하고 화면을 이동시키는 방식을 포함하므로 SPA에서 사용하기에는 부적합하다.
SPA에서 화면 이동없이 url을 업데이트하는 기능에 주로 사용되는 방법이 History 조작이고 이는 History API를 통해 가능하다.
forward
, backward
, go
라는 메서드도 있지만 페이지 이동이 일어나므로 SPA에는 부적합하다.
프로그램 내부적으로는 Histroy API를 활용해 페이지 로드를 없에더라도 사용자가 앞/뒤로가기 버튼을 누르면 문제가 된다.
따라서 popstate
이벤트에 핸들러를 달고 e.preventDefault
를 통해 앞/뒤로가기 버튼의 기본 기능을 막고 SPA의 방식으로 돌아가도록 커스텀하는게 일반적이다.
<a>
같은 경우에도 같은 방식으로 클릭 이벤트에서 e.preventDefault
를 이용한다.
직접 url 입력이나 새로고침 같은 경우는 요청을 이벤트로 제어할 수 없으므로 서버에서 모든 요청에 기본 index.html 파일만 응답하도록 하는 처리가 되어있어야 한다.
기본 페이지를 받아오더라도 url 정보는 세션 히스토리에 남으니 로딩할 때 url에 맞게 컴포넌트를 렌더링해주면 된다.
왜 굳이 다른 태그 안쓰고 a 태그 기능 막아가면서 쓰느냐는 Semantic 측면을 고려해야하기 때문이다.
검색 엔진의 크롤러든 타 개발자든 누가 보더라도 이게 링크라는 인식을 주는 게 가독성와 활용도를 높일 수 있다.
별거 아니겠거니 하고 작성을 시작했는데 popstate의 문서 설명이 너무 어려워서 시간을 많이 썼다. 그런데 결론도 제대로 못 낸 느낌이라서 아쉽다.