History API를 이용한 시간 여행
우리는 이렇게 생긴 뒤로 가기, 앞으로 가기 버튼을 이용해 30분 전에 봤던 페이지로 돌아갈 수도 있고 가장 최근에 본 페이지로 다시 이동할 수도 있습니다. 이것이 가능한 이유는 어딘가에 기록들이 저장되어 있기 때문입니다.
사용자가 어떤 페이지를 방문할 때마다 브라우저의 세션 히스토리 스택에는 페이지에 대한 기록이 쌓입니다.
하나의 페이지에 대한 정보는 하나의 엔트리에 저장되며, 엔트리는 state
와 url
정보를 가지고 있습니다.
History API는 세션 히스토리에 접근하여 엔트리를 조작할 수 있는 기능을 제공합니다.
history 전역 객체를 통해 다음과 같은 메서드들을 사용할 수 있습니다.
1. history.back()
뒤로 가기
2. history.forward()
앞으로 가기
3. history.go(n)
현재 페이지를 기준으로 상대적인 위치 n만큼 이동
예를 들어 go(-1)
은 back()
과 같습니다. forward()
는 go(1)
과 같습니다.
4. pushState(state, [unused], [optional] url)
히스토리 스택에 직접 엔트리를 추가합니다.
첫 번째 인자로는 페이지와 관련된 정보를 넘길 수 있습니다.
두 번째는 사용하지 않는 값이니 공백을 넣습니다.
마지막으로 주소를 넣을 수 있습니다.
이 함수를 이용하면 현재 페이지에서 벗어나지 않고 주소창에 있는 주소를 변경할 수도 있습니다.
개발자 도구를 열어 콘솔창에 아래와 같이 입력을 해보면 좀 더 명확하게 이해할 수 있습니다.
history.pushState({page_no:1, data:'abc'}, '', location.href + '/1'); |
현재 페이지의 주소는 co1nam.tistory.com/108
입니다.
위 문장을 실행할 경우 현재 페이지를 유지하면서 주소만 co1nam.tistory.com/108/1
로 바뀌게 됩니다.
다시
history.pushState({page_no:2, data:'def'}, '', location.href + '/2'); |
를 실행하면 co1nam.tistory.com/108/1/2
로 바뀌게 되고
히스토리 스택에 엔트리가 추가되었으므로 여기서 뒤로 가기를 클릭하면 다시 co1nam.tistory.com/108/1
로 돌아옵니다.
5. replaceState(state, [unused] title, [optional] url)
co1nam.tistory.com/108/1
에서 아래와 같이 replaceState()
를 실행하면 주소가 co1nam.tistory.com/108/aa
로 바뀝니다.
history.replaceState({page_no:2, data:'def'}, '', 'aa'); |
pushState()
가 새로운 엔트리를 추가한 뒤 활성화하는 것과 달리
replaceState()
는 입력받은 정보로 현재 엔트리의 state
와 url
을 대체합니다.
따라서 뒤로 가기를 누르면 co1nam.tistory.com/108/1
이 아닌 co1nam.tistory.com/108
로 이동하게 됩니다.
6. popstate 이벤트
back()
, forward()
나 뒤로 가기 또는 앞으로 가기를 통해 히스토리를 탐색할 때마다 popstate
이벤트가 발생합니다.
pushState()
또는 replaceState()
에 의해서는 popstate
이벤트가 발생하지 않습니다.
다들 알고 계시겠지만 스택에 요소를 삽입하는 것을 push, 스택에 있는 요소를 꺼내오는 것을 pop이라고 하기 때문에 저런이름이 붙은 겁니다.
popstate
에 이벤트 리스너를 추가한 다음 앞서 했던 것처럼 pushState()
를 이용해 히스토리 스택을 쌓아줍시다.
window.addEventListener("popstate", (e) => {
console.log(JSON.stringify(e.state));
});
뒤로 가기나 앞으로 가기를 할 때마다 콘솔창에 엔트리가 가지고 있는 state
정보가 출력되는 것을 확인할 수 있습니다.