ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • History API 와 클라이언트 라우팅
    FE 2025. 9. 8. 23:07

    🚀 SPA

    SPA는 URL이 바뀔 때마다 새로운 페이지를 서버로 요청하지 않고 클라이언트 단에서 라우팅을 합니다.

    • React, Svelte, Vue.js 같은 대부분의 프론트엔드 프레임워크를 사용할 때 이런 클라이언트 단 라우팅을 지원하는 라이브러리를 사용합니다.

    ✅ 이런 라우팅 라이브러리는 내부적으로 자바스크립트의 History API를 사용하고 있습니다.

     

    🧩 SPA에서 URL Routing이 필요한 이유

     

    🤔 만약 URL Routing이 없다면?

    • SPA에서는 실제 html 파일은 하나로
    • 여러 페이지를 돌아다녔지만 방문 기록이 없습니다.
    • 따라서 뒤로가기 / 앞으로 가기 등의 기능을 사용할 수 없습니다.
    • 본인이 보고 있는 페이지의 접근 방법을 알기 어렵습니다.

     

    즉 SPA역시 우리가 알고 있는 웹페이지와 같은 사용자 경험을 제공해주어야 합니다.

     

    🌠 History API란?

    History API는 브라우저가 관리하는 세션 히스토리(session history) , 즉 페이지 방문 이력을 제어하기 위한 웹 표준 API 입니다.

    여기서 세션은 보통 새 창이나 탭을 열 때 생성되고 해당 창이나 탭을 닫을 때 사라집니다.

     

    🤥 세션 히스토리

    웹 브라우저에서 세션 히스토리는 사용자가 현재 탭에서 이동했던 페이지 탐색 기록

    • 각 브라우저 탭 / 창별로 관리되는 방문 기록

     

    📖 history 전역 객체

    자바스크립트에서 History API는 기본적으로 history 전역 객체를 통해서 사용해 볼 수 있으며 window나 document 전역 객체를 통해서도 접근할 수 있습니다.

     

    🔖  history 

    history.length 세션 히스토리에 들어있는 요소들 개수 확인
    history.back() 뒤로 가기
    history.forward() 앞으로 가기
    history.go(number) 원하는 위치만큼 이동

     

     

    이렇게 현재 세션에서 얼마나 많은 페이지를 방문했는지 알고 싶다면 다음과 같이 History API에서 제공하는 length 프로퍼티에 접근하면 됩니다.

     

    history.length; // 1
    window.history.length; // 1
    document.history.length; // 1

     

    ⏩ 기록된 방문 이력을 통한 페이지 이동

    History API가 제공하는 가장 기본적인 기능은 히스토리에 기록된 페이지 방문 이력에 따라 이동하는 것입니다.

    • 뒤로 가기 앞으로 가기 등의 기능을 자바스크립트로 대신 처리
    history.back(); // 뒤로 가기
    history.forware(); // 앞으로 가기

     

    🏃‍♂️ go

    • back(), forward()를 대체할 수 있는 좀 더 범용적인 메서드
    history.go(-2); // 뒤로 2번가기
    history.go(0); // 새로 고침
    history.go(2); // 앞으로 2번가기

     

    🚨 back / forward / go 메서드는 SPA에서 잘 사용하지 않습니다!

    이 3개의 메서드를 호출하면 브라우저는 해당 페이지를 리로드(reload)하기 때문에

     

    ⭐ 세션 히스토리 변경

    📌 pushState(state, unused, url)

    파라미터로 들어온 url을 현재 state의 다음 state로 추가하고 뒤에 있던 state은 모두 날려버립니다.

    • 새로 들어온 url이 가장 최상위 state

     

    ✔️ 매개변수

    매개변수 설명 특징
    state pushState()에 의해 생성되어 새로운 히스토리 항목과 관련된 JS 객체 사용자가 새로운 state로 이동할 때마다 popstate 이벤트가 발생되고 이벤트 state 속성은 기록 항목의 state 객체 복사본을 포함합니다.
    unused 예전 브라우저들과의 호환성을 위해 강제로 넣는 값 생략 불가능 - 빈 문자열
    url 새로 히스토리에 쌓을 url 현재 url과 origin(protocol + host + port)이 같은 절대 또는 상대 경로, 주소창은 바뀌지만 실제 페이지는 이동하지 않습니다.

    https://alpha.velog.io/@kim_unknown_/JavaScript-History-API

     

    그림에서 보이는 것 처럼 pushState() 메서드를 호출하면 원래 있던 페이지는 이전 페이지로 저장이 되고 인자로 넘긴 URL이 현재 페이지가 됩니다.

     

    사용자가 브라우저에서 뒤로 가기 버튼을 눌러서 원래 페이지로 돌아가능 것이 가능합니다.

     

    하지만 앞으로 가기 버튼은 사용할 수 없게 됩니다.

    • 원래 있던 이후의 방문 히스토리를 모두 지우기 때문

     

    📌 replaceState(state, unused, url)

    • 파라미터는 pushState 와 동일

     

    파라미터로 들어온 url로 현재 페이지의 url을 변경

    • 새로운 state를 쌓는 것이 아닌 현재 state를 대체

    https://alpha.velog.io/@kim_unknown_/JavaScript-History-API

     

    replaceState() 메서드를 호출하면 원래 페이지가 인자로 넘긴 URL로 변경됩니다.

     

    따라서 사용자가 브라우저에서 뒤로 가기 버튼을 누르면 원래 페이지의 이전 페이지로 이동하고 앞으로 가기 버튼을 누르면 기존의 다음 페이지로 이동할 수 있습니다.

     

    📌 popstate 이벤트

    History API의 pushState(), replaceState() 메서드를 사용하면 페이지 리로딩없이 URL만 갱신하여 클라이언트 단에서 라우팅이 가능합니다.

     

    만약, 사용자가 브라우저에서 뒤로 가기 또는 앞으로 가기를 하게 된다면 back(), forward() 메서드 처럼 브라우저가 페이지를 다시 불러오게 되고 이는 SPA의 방식과 맞지 않게 동작하게 됩니다.

     

    ⚠️ 하지만 브라우저에서 뒤로 가기 / 앞으로 가기 버튼은 우리가 통제할 수 있는 페이지 밖에 있어 일반적인 버튼처럼 click 이벤트를 감지할 수 없습니다.

    • 이런 문제를 해결하기 위한 방법이 History API의 popstate 이벤트 입니다.

     

    📖 popstate

     

    사용자가 브라우저에서 뒤로 가기나 앞으로 가기를 할 때 window 전역 객체에서 발생해 자바스크립트로 이벤트 핸들러를 걸어 처리할 수 있습니다.

    • 사용자의 세션 기록 탐색으로 인한 같은 문서내의 히스토리 엔트리가 바뀔때마다 발생하는 이벤트
    • window에서 발생하기 때문에 window에 이벤트 리스너를 추가해 어떤 state가 pop되는지 확인할 수 있습니다.

     

    pushState() 메서드나 replaceState() 메서드에 의해 생성되면 popstate 이벤트의 state 속성은 히스토리 엔트리 state 객체의 복사본을 갖게 됩니다.

    • pushState() 메서드나 replaceState() 메서드가 첫 번째 인자로 상태 객체를 받는 이유
    • popstate 이벤트를 처리하는 핸들러 함수의 매개변수로 이 상태 객체가 넘어옵니다.

     

    window.addEventListeneer("popstate", (event) => {});

     

    🧑‍💻 여러 프레임워크에서의 라우팅

    🤖 Vue 프레임워크에서의 라우팅

    📖 History API를 이용한 Vue 라우팅

     

    Vue Router는 내부적으로 window.history를 직접 사용합니다.

     

    router/packages/router/src/history/html5.ts

    // function useHistoryStateNavigation()
    history[replace ? 'replaceState' : 'pushState'](state, '', url)

     

    👻 React 프레임워크에서의 라우팅

    📖 History API를 이용한 React 라우팅

    • createBrowserRouter → createBrowserHistory → getUrlBaseHistory 순서로 History API를 사용합니다.

     

    createBrowserRouter
        ↓
    createBrowserHistory
        ↓
    getUrlBaseHistory (push, replace 등 내부 동작)

     

    1️⃣ createBrowserRouter

    • 라우터 초기화 단계
    • 라우트 설정 객체를 받아, 라우팅 정보(path, element 등)를 관리할 수 있는 Router 인스턴스 생성

     

    2️⃣ createBrowserHistory

    • 브라우저의 window.history 객체를 직접 사용하여 확장한 history 객체를 생성
    • 내부적으로 pushState, replaceState, popstate 이벤트를 활용
    • 결과적으로 SPA 전용 브라우저 히스토리 관리 객체를 반환

     

    3️⃣ getUrlBaseHistory

     

    push

    • push 메서드는 window.history.pushState를 래핑하여 새로운 URL을 스택에 추가합니다.

     

    ✏️ 정리

    • Vue와 React 모두 브라우저 History API(pushState, replaceState, popstate)를 활용한다.
    • Vue Router는 window.history를 직접 사용하고 React Router는 이를 확장한 createBrowserHistory를 사용한다.
    • push → 주소창 변경 + SPA 내부 렌더링, popstate → 뒤로 가기/앞으로 가기 시 동작.
    • 결과적으로 서버에 불필요한 요청 없이 URL과 화면 전환을 동기화하는 것이 핵심.
    • React Router는 createBrowserHistory로 커스텀 제어가 가능해 로그 추적이나 사용자 행동 분석에도 활용할 수 있다.

     

    'FE' 카테고리의 다른 글

    프론트엔드 빌드, 번들러  (0) 2025.09.22
    DocumentFragment으로 DOM 조작하기  (0) 2025.09.08
    프론트엔드 아키텍처 구조 - MVC, MVVM  (0) 2025.09.02

    댓글

Designed by Tistory.