JavaScript History API와 URL 관리 가이드

Rachel·2024년 8월 8일
0

JavaScript

목록 보기
2/2
post-thumbnail

애플리케이션을 구현하다보면 특정 상황에서 뒤로 가기를 했을 때 예상되는 페이지가 있거나 의도하는 페이지로 이동을 시도하는 상황이 생길 수 있습니다.
History API나 URL 변경 방식을 제대로 알지 못하면 뒤로 가기를 했을 때 엉뚱한 곳으로 가는 상황이 생기거나, 특정 URL로 변경하려면 어떻게 해야 하는지 모르기 때문에 이에 대한 학습이 필요해 한 번 정리해봤습니다.

JavaScript의 History API

JavaScript의 History API는 웹 브라우저의 세션 기록(history)을 조작할 수 있는 강력한 도구입니다. 이를 통해 개발자는 사용자가 방문한 페이지의 URL을 변경하거나, 뒤로 가기/앞으로 가기 기능을 제어할 수 있습니다. History API는 주로 단일 페이지 애플리케이션(SPA)에서 사용됩니다.

참고 - MDN History API

⭐️ 주요 메서드 및 속성

  1. history.length
    현재 브라우저 세션의 기록 목록에 있는 항목의 수를 반환합니다.

    console.log(history.length); // 예: 5
  2. history.state
    현재 기록 항목과 관련된 상태 객체를 반환합니다.

    console.log(history.state);
  3. history.back()
    세션 기록에서 이전 페이지로 이동합니다.

    history.back();
  4. history.forward()
    세션 기록에서 다음 페이지로 이동합니다.

    history.forward();
  5. history.go(n)
    세션 기록에서 특정 위치로 이동합니다. n이 0이면 현재 페이지를 다시 로드하고, 양수이면 앞으로, 음수이면 뒤로 이동합니다.

    history.go(n);
  6. history.pushState(state, title, url)
    세션 기록 스택에 상태를 추가합니다. URL을 변경하지만 페이지를 새로 고침하지 않습니다.

    history.pushState({ page: 1 }, "title 1", "/page1");
  7. history.replaceState(state, title, url)
    현재 기록 항목을 주어진 상태와 URL로 바꿉니다.

    history.replaceState({ page: 2 }, "title 2", "/page2");

뒤로 가기, 앞으로 가기 이벤트

window.onpopstate 이벤트
브라우저의 뒤로 가기 또는 앞으로 가기 버튼을 누르거나, history.back(), history.forward(), history.go() 메서드를 호출할 때 발생합니다. 이 이벤트를 통해 상태를 복원할 수 있습니다.

window.onpopstate = function (event) {
  console.log(
    "location: " + document.location + ", state: " + JSON.stringify(event.state)
  );
  // 상태 복원 로직
};
window.addEventListener("popstate", (event) => {
  alert(
    `location: ${document.location}, state: ${JSON.stringify(event.state)}`
  );
});

history.pushState({ page: 1 }, "title 1", "?page=1");
history.pushState({ page: 2 }, "title 2", "?page=2");
history.replaceState({ page: 3 }, "title 3", "?page=3");
history.back(); // "location: http://example.com/example.html?page=1, state: {"page":1}"라는 알림이 발생합니다.
history.back(); // "location: http://example.com/example.html, state: null"라는 알림이 발생합니다.
history.go(2); // "location: http://example.com/example.html?page=3, state: {"page":3}"라는 알림이 발생합니다.

세션 기록 동작 단계별 자세한 설명

  1. history.pushState({ page: 1 }, "title 1", "?page=1");
    • 현재 페이지 URL은 http://example.com/example.html입니다.
    • pushState는 현재 URL을 http://example.com/example.html?page=1로 변경하고, 상태 { page: 1 }를 기록에 추가합니다.
    • 세션 기록 스택: [null, { page: 1 }]
    • 현재 페이지: http://example.com/example.html?page=1

  2. history.pushState({ page: 2 }, "title 2", "?page=2");
    • 현재 페이지 URL은 http://example.com/example.html?page=1입니다.
    • pushState는 현재 URL을 http://example.com/example.html?page=2로 변경하고, 상태 { page: 2 }를 기록에 추가합니다.
    • 세션 기록 스택: [null, { page: 1 }, { page: 2 }]
    • 현재 페이지: http://example.com/example.html?page=2

  3. history.replaceState({ page: 3 }, "title 3", "?page=3");
    • 현재 페이지 URL은 http://example.com/example.html?page=2입니다.
    • replaceState는 현재 URL을 http://example.com/example.html?page=3로 변경하고, 상태 { page: 3 }로 기존 상태를 대체합니다.
    • 세션 기록 스택: [null, { page: 1 }, { page: 3 }]
    • 현재 페이지: http://example.com/example.html?page=3

  4. history.back();
    • 현재 페이지 URL은 http://example.com/example.html?page=3입니다.
    • back 메서드는 세션 기록에서 이전 항목으로 이동합니다.
    • 이동 후 페이지 URL: http://example.com/example.html?page=1
    • 상태: { page: 1 }
    • 콘솔 출력: "location: http://example.com/example.html?page=1, state: {"page":1}"

  5. history.back();
    • 현재 페이지 URL은 http://example.com/example.html?page=1입니다.
    • back 메서드는 세션 기록에서 이전 항목으로 이동합니다.
    • 이동 후 페이지 URL: http://example.com/example.html
    • 상태: null
    • 콘솔 출력: "location: http://example.com/example.html, state: null"

  6. history.go(2);
    • 현재 페이지 URL은 http://example.com/example.html입니다.
    • go 메서드는 세션 기록에서 지정된 위치로 이동합니다. 2는 두 단계 앞으로 이동하는 것을 의미합니다.
    • 이동 후 페이지 URL: http://example.com/example.html?page=3
    • 상태: { page: 3 }
    • 콘솔 출력: "location: http://example.com/example.html?page=3, state: {"page":3}"

URL 관련 메서드 및 속성

1. window.location

window.location 객체는 현재 문서의 URL을 나타내며, URL과 관련된 여러 정보를 얻고 변경할 수 있는 속성과 메서드를 제공합니다.

window는 브라우저 환경에서 자바스크립트 코드가 실행될 때 제공되는 전역 객체.
window 객체의 모든 속성과 메서드는 전역 네임스페이스에 존재하므로 window 생략 가능.

주요 속성

  1. window.location.href
    현재 페이지의 전체 URL을 반환하거나 설정합니다.

    console.log(window.location.href); // "https://www.example.com/path/page.html"
    window.location.href = "https://www.example.com/newpage.html"; // 페이지 이동
  2. window.location.protocol
    URL의 프로토콜 부분을 반환합니다. (예: “http:”, “https:”)

    console.log(window.location.protocol); // "https:"
  3. window.location.host
    호스트 이름과 포트 번호를 반환합니다. (예: “www.example.com:80”)

    console.log(window.location.host); // "www.example.com"

    ✅ 표준 포트 번호 생략
    HTTP (포트 80) > HTTPS (포트 443)
    표준 포트를 사용할 경우 window.location.host는 포트 번호를 포함하지 않고 호스트 이름만 반환.

  4. window.location.hostname
    호스트 이름을 반환합니다. (예: “www.example.com”)

    console.log(window.location.hostname); // "www.example.com"
  5. window.location.port
    포트 번호를 반환합니다. (예: “80”, “443”)

    console.log(window.location.port); // "443"
  6. window.location.pathname
    URL의 경로 부분을 반환합니다. (예: “/path/page.html”)

    console.log(window.location.pathname); // "/path/page.html"
  7. window.location.search
    URL의 쿼리 문자열 부분을 반환합니다. (예: “?name=value”)

    console.log(window.location.search); // "?name=value"
  8. window.location.hash
    URL의 해시(#) 부분을 반환합니다. (예: “#section1”)

    console.log(window.location.hash); // "#section1"
  9. window.location.origin
    현재 URL의 원점을 반환합니다. (예: “https://www.example.com”)

    console.log(window.location.origin); // "https://www.example.com"

⭐️ 주요 메서드 - 원하는 URL로 조작하기

참고

  1. window.location.assign(url)
    지정된 URL로 이동합니다.

    window.location.assign("https://www.example.com");
  2. window.location.replace(url)
    지정된 URL로 이동하며, 현재 페이지를 브라우저 히스토리에서 제거합니다. 즉, 뒤로 가기 버튼을 눌렀을 때 replace 메서드로 이동하기 전 페이지로 돌아갈 수 없습니다.

    window.location.replace("https://www.example.com");
  3. window.location.reload(forceReload)
    현재 문서를 다시 로드합니다. forceReload가 true이면 서버에서 새로고침을 강제하고, false이면 캐시된 버전을 사용할 수 있습니다.

    window.location.reload(); // 기본: 캐시된 버전을 사용할 수 있음
    window.location.reload(true); // 서버에서 새로고침을 강제

2. document API

document 객체는 웹 페이지의 콘텐츠를 조작할 수 있는 API를 제공합니다. 이는 DOM(Document Object Model)을 통해 HTML 문서 구조를 표현하며, JavaScript로 웹 페이지를 동적으로 변경할 수 있게 해줍니다. document 객체를 사용하여 웹 페이지의 요소를 탐색하고, 수정하고, 이벤트를 추가할 수 있습니다.

URL 관련

  1. document.location
    window.location 객체와 동일하게 현재 문서의 URL을 반환하거나 설정합니다.

    console.log(document.location.href); // 현재 URL을 출력
    document.location.href = "https://www.example.com"; // 새 URL로 이동
  2. document.referrer
    현재 문서를 참조한 문서의 URL을 반환합니다.

    console.log(document.referrer); // 사용자가 이 페이지로 오기 전의 페이지 URL을 출력

URL, URI, URN 개념 및 URL의 각 부분

✏️ URL, URI, URN 개념 정리

  • URI (Uniform Resource Identifier): 웹 상의 자원을 식별하는 문자열입니다. URI는 URL과 URN을 포함하는 상위 개념입니다. URI는 특정 리소스에 대한 식별 정보를 제공합니다.
  • URL (Uniform Resource Locator): 자원의 위치를 나타내는 URI의 한 형태로, 프로토콜, 호스트, 경로 등 자원의 접근 방법을 포함합니다. 예: https://www.example.com/path/to/resource.
  • URN (Uniform Resource Name): 자원의 이름을 나타내는 URI의 한 형태로, 자원의 위치와 관계없이 고유하게 식별합니다. 예: urn:isbn:0451450523.

참고 - difference-between-uri-url
참고 - URI

URL의 각 부분에 대한 이해

URL(Uniform Resource Locator)은 웹 상의 자원을 식별하는 문자열입니다. URL은 여러 부분으로 구성되며, 각 부분은 특정한 역할을 합니다.

  1. 프로토콜 (Scheme)
    자원에 접근하기 위해 사용하는 프로토콜을 지정합니다.
    예: http, https, ftp
    예시: https://

  2. 호스트 (Host)
    자원이 위치한 서버의 도메인 이름 또는 IP 주소를 지정합니다.
    예: www.example.com
    예시: https://www.example.com

  3. 포트 (Port)
    서버의 특정 네트워크 포트를 지정합니다. 기본 포트를 사용하는 경우 생략될 수 있습니다.
    예: :80, :443
    예시: https://www.example.com:443

  4. 경로 (Path)
    서버 상의 특정 자원에 대한 경로를 지정합니다.
    예: /path/to/resource
    예시: https://www.example.com/path/to/resource

  5. 쿼리 문자열 (Query String)
    자원에 대한 추가적인 매개변수를 지정합니다. ?로 시작하며 &로 구분됩니다.
    예: ?key1=value1&key2=value2
    예시: https://www.example.com/path/to/resource?key1=value1&key2=value2

  6. 프래그먼트 (Fragment)
    문서 내의 특정 부분을 지정합니다. #로 시작합니다.
    예: #section1
    예시: https://www.example.com/path/to/resource?key1=value1&key2=value2#section1

전체 URL 예시: https://www.example.com:443/path/to/resource?key1=value1&key2=value2#section1

• 프로토콜: https
• 호스트: www.example.com
• 포트: 443
• 경로: /path/to/resource
• 쿼리 문자열: ?key1=value1&key2=value2
• 프래그먼트: #section1

정리 - 실제 예시

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>URL Parts Example</title>
  </head>
  <body>
    <button onclick="showURLParts()">Show URL Parts</button>

    <script>
      function showURLParts() {
        console.log("전체 URL: " + location.href);
        console.log("프로토콜: " + location.protocol);
        console.log("호스트: " + location.host);
        console.log("호스트 이름: " + location.hostname);
        console.log("포트: " + location.port);
        console.log("경로: " + location.pathname);
        console.log("쿼리 문자열: " + location.search);
        console.log("프래그먼트: " + location.hash);
      }
    </script>
  </body>
</html>

History API 실제 사용 예시

React

React에서는 React Router를 사용하여 History API를 쉽게 사용할 수 있습니다. React Router는 SPA에서 클라이언트 측 라우팅을 처리하는 데 사용됩니다.

import React from "react";
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";

function Home() {
  return <h1>Home</h1>;
}

function About() {
  return <h1>About</h1>;
}

function Contact() {
  return <h1>Contact</h1>;
}

function App() {
  return (
    <Router>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/contact">Contact</Link>
      </nav>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </Switch>
    </Router>
  );
}

export default App;

참고 - React Router 공식 문서

Next.js

Next.js는 서버 사이드 렌더링(SSR)을 지원하는 React 프레임워크입니다. Next.js에서는 기본적으로 페이지 간 이동이 서버 측에서 처리되지만, 클라이언트 측 네비게이션을 위해 next/router, next/navigation을 사용할 수 있습니다.

Page Router

next/router를 사용합니다.

import { useRouter } from "next/router";

function Home() {
  const router = useRouter();

  const navigateTo = (url) => {
    router.push(url);
  };

  return (
    <div>
      <h1>Home</h1>
      <button onClick={() => navigateTo("/about")}>Go to About</button>
      <button onClick={() => navigateTo("/contact")}>Go to Contact</button>
    </div>
  );
}

export default Home;

참고 - Next.js 공식 문서 Page Router/useRouter

App Router

next/navigation을 사용합니다.

"use client";

import { useRouter } from "next/navigation";

export default function Page() {
  const router = useRouter();

  return (
    <button type="button" onClick={() => router.push("/dashboard")}>
      Dashboard
    </button>
  );
}

참고 - Next.js 공식 문서 App Router/useRouter


추가하면 좋은 부분이나 잘못된 점이 있다면 댓글 남겨주세요. 감사합니다 :)

profile
기존 블로그: https://hi-rachel.tistory.com

0개의 댓글