올바른 이해와 사용 방법
window.history.pushState() 메서드를 사용하면 새로운 페이지를 서버에 요청하지 않고 브라우저의 현재 창이나 탭의 방문 기록(Session History)에 새로운 항목(entry)을 추가하면서 URL을 변경할 수 있습니다.
참고하세요!
window.history.pushState() 메서드는 줄여서 history.pushState()라고만 작성하는 경우도 많습니다.
브라우저에서는 window 객체가 전역 객체이므로, window.history는 줄여서 history만으로도 동일하게 사용할 수 있습니다.
이 기능은 페이지를 새로고침하지 않고 화면의 일부만 변경하는 SPA(Single Page Application)에서 자주 사용됩니다.
특징
- 새로운 페이지를 서버에 요청하지 않고 현재 창이나 탭의 방문 기록(Session History)에 새로운 항목을 추가합니다.
- 새로운 방문 기록의 추가와 함께 URL도 변경할 수 있습니다.
- URL 변경 시 브라우저는
pushState()호출 후 이 URL의 페이지를 새로 로드하지 않으며, 주소창의 URL만 변경됩니다. - 필요에 따라 상태(State) 데이터도 저장할 수 있습니다.
구문
window 객체는 생략할 수 있으며, 보통 history.pushState()를 사용합니다.
history.pushState(state, unused)
history.pushState(state, unused, url)
// 또는
window.history.pushState(state, unused)
window.history.pushState(state, unused, url)
매개변수
state |
|
|---|---|
unused |
이 매개변수는 역사적인 이유로 존재하며 현재는 사용되지 않습니다. 일반적으로 관례상 빈 문자열("")을 지정합니다. |
url |
|
반환 값
없습니다. 즉, undefined를 반환합니다.
사용법 참고 사항
pushState()로 추가된 방문 기록 항목은 브라우저의 '뒤로 가기'와 '앞으로 가기' 탐색 대상이 됩니다. 이전 항목으로 이동하면 해당 항목에 저장된 상태(State) 데이터도 복원됩니다.pushState()는 페이지를 새로고침하지 않습니다. 현재 문서를 그대로 유지한 상태에서 방문 기록과 상태(State) 데이터, 그리고 주소창의 URL만 변경합니다.
예제
/* 초기 URL 예: https://www.example.com/ */
// 1. 상태 { page: 1 } 저장 + URL 변경
history.pushState({ page: 1 }, "", "/page-1");
console.log("현재 state:", history.state); // 출력: {page: 1}
// 현재 URL: https://www.example.com/page-1
// 2. 상태 { page: 2 } 저장 + URL 변경
history.pushState({ page: 2 }, "", "/page-2");
console.log("현재 state:", history.state); // 출력: {page: 2}
// 현재 URL: https://www.example.com/page-2
/* 3. 브라우저의 '뒤로 가기' 버튼을 누르면
주소창은 다시 /page-1로 변하고,
history.state는 { page: 1 }로 복원됩니다.
*/
코드 부연설명
window.history.state 속성은 현재 창이나 탭의 브라우저 방문 기록에 저장된 상태(State) 데이터를 반환합니다.
참고하세요!
window.history.pushState() 메서드는 줄여서 history.pushState()라고만 작성하는 경우가 많은 것처럼
window.history.state 속성도 줄여서 history.state라고만 작성하는 경우도 많습니다.
주의할 점
window.history.pushState() 메서드는 페이지를 새로 불러오지 않고 방문 기록과 URL을 변경할 수 있어 동적인 웹 페이지를 구현할 때 유용하게 활용되지만 구현 과정에서 몇 가지 주의할 점이 있습니다.
동일 출처 정책(Same-Origin Policy) 제한
pushState(state, unused, url)에 전달하는 세 번째 매개변수(url)는 현재 페이지와 반드시 동일한 출처(도메인, 프로토콜, 포트)를 가져야 합니다. 동일하지 않은 출처 URL을 지정하면 SecurityError가 발생합니다.
SecurityError가 발생
/* 현재 페이지 URL 예: https://www.example.com/ */
history.pushState({}, "", "https://www.cross-example.com/"); // 다른 도메인으로의 변경
상태(State) 데이터의 크기 및 종류 제한
pushState(state, unused, url)에 전달하는 첫 번째 매개변수(state)는 새롭게 추가할 방문 기록에 저장할 상태(State) 데이터입니다. 객체(Plain objects, 일반 객체)뿐만 아니라 문자열, 숫자, 배열 등 구조화 가능한(Structured Clone) 자바스크립트 데이터라면 무엇이든 저장할 수 있습니다.
이때 전달하는 상태(State) 데이터는 브라우저가 방문 기록(Session History)과 함께 내부적으로 저장하며, 브라우저에 따라 크기 제한이 있습니다. 따라서 대용량 이미지 바이너리 데이터나 매우 큰 객체 또는 배열 등을 전달하면 예외가 발생할 수 있습니다.
또한 데이터가 DOM 요소나 함수, 순환 참조를 가진 객체 등인 경우는 구조화 가능한(Structured Clone) 데이터가 아니기 때문에 저장할 수 없습니다.
pushState() 호출 자체는 popstate 이벤트를 발생시키지 않음
브라우저의 방문 기록(Session History)이 변경되어 이전 페이지 또는 다음 페이지로 이동할 때, 즉 현재 표시되고 있는 방문 기록 항목(현재 활성화된 항목)이 다른 항목으로 전환된 후 발생하는 이벤트가 popstate 이벤트입니다.
방문 기록이 변경될 때 발생하는 popstate 이벤트를 참조하세요.
브라우저의 방문 기록(Session History)에 pushState() 호출로 새로운 방문 기록을 추가할 때에는 popstate 이벤트가 발생하지 않습니다. 즉, 기존에 있던 방문 기록 항목(entry) 사이를 오갈 때 발생합니다.
pushState() 호출 자체는 popstate 이벤트를 발생시키지 않지만 pushState() 호출 후 사용자가 브라우저의 "뒤로 가기" 버튼을 눌렀을 때에는 popstate 이벤트가 발생합니다.
새로고침 시 404 에러 (서버 설정 고려)
pushState() 호출은 브라우저 주소창의 URL만 바꿀 뿐, 서버로 실제 요청을 보내지 않습니다. 하지만 사용자가 그 상태에서 새로고침(F5)을 하거나 해당 URL을 복사해 직접 주소창에 입력하고 접속하면, 브라우저는 변경된 URL에 해당하는 페이지를 서버에 요청합니다.
URL 경로가 /page-1에서 pushState() 호출로 인해 /page-2로 변경되었다고 가정해 보겠습니다.
사용자가 변경된 경로로 직접 방문했을 때, 브라우저는 서버에 변경된 /page-2 경로를 가지고 있는 URL에 해당하는 페이지를 요청하게 됩니다. 이때, 실제 /page-2 에 해당하는 페이지가 없어 서버가 그 URL을 처리하지 못한다면 404 Not Found 에러가 발생합니다.
이런 상황은 pushState() 호출로 인해 /page-2로 변경된 URL을 사용자가 그 상태에서 새로고침(F5)하는 경우에도 발생합니다.
따라서 이러한 점을 대비하여 서버 설정을 반드시 고려해야 합니다.
명세서
| 명세서 사양 | |
|---|---|
window.history.pushState()
|
HTML #dom-history-pushstate-dev |
브라우저 호환성
| 메서드 |
데스크탑 Chrome
|
데스크탑 Edge
|
데스크탑 Firefox
|
Safari
|
|---|---|---|---|---|
window.history.pushState()
|
5 | 12 | 4 | 5 |