4.Navigation

Web APIs - History

์›น ๊ฐœ๋ฐœ์—์„œ History API๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ธฐ๋ก์„ ์กฐ์ž‘ํ•˜๊ณ  ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋ฐ ์†์„ฑ ์ง‘ํ•ฉ์ด๋‹ค. History API๋Š” ํƒ์ƒ‰ ๊ธฐ๋ก์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•ž๋’ค๋กœ ํƒ์ƒ‰ํ•˜๊ณ  URL์„ ์ˆ˜์ •ํ•˜๊ณ  ํƒ์ƒ‰ ์ด๋ฒคํŠธ๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

History API์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

  1. ๊ธฐ๋ก ๊ฐœ์ฒด(The history Object): ๊ธฐ๋ก API์˜ ์ค‘์‹ฌ ๊ฐœ์ฒด๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ์„ธ์…˜ ๊ธฐ๋ก์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ธฐ๋ก ๊ฐœ์ฒด๋‹ค. window.history ์†์„ฑ์„ ํ†ตํ•ด ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ก ๊ฐœ์ฒด๋Š” ๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ํƒ์ƒ‰ํ•˜๊ณ  ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ์™€ ์†์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

  2. ๊ธฐ๋ก ํƒ์ƒ‰(Navigating History): ๊ธฐ๋ก ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž์˜ ๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์‚ฌ์šฉ๋ฒ•

  • go(): ์ฃผ์–ด์ง„ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํžˆ์Šคํ† ๋ฆฌ์˜ ํŠน์ • ์ง€์ ์œผ๋กœ ์ด๋™ํ•œ๋‹ค. ์–‘์ˆ˜ ๊ฐ’์€ ์•ž์œผ๋กœ ์ด๋™ํ•˜๊ณ  ์Œ์ˆ˜ ๊ฐ’์€ ๋’ค๋กœ ์ด๋™ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด history.go(-1)๋Š” ํ•œ ํŽ˜์ด์ง€ ๋’ค๋กœ ์ด๋™ํ•œ๋‹ค.

  • back(): history.go(-1)์™€ ๋™์ผํ•˜๋ฉฐ ํ•œ ํŽ˜์ด์ง€ ๋’ค๋กœ ์ด๋™ํ•œ๋‹ค.

  • forward(): history.go(1)์™€ ๋™์ผํ•˜๋ฉฐ ํ•œ ํŽ˜์ด์ง€ ์•ž์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

  • pushState(): ๋ธŒ๋ผ์šฐ์ €์˜ ๊ธฐ๋ก ์Šคํƒ์— ์ƒˆ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. state(์ƒˆ ๊ธฐ๋ก ํ•ญ๋ชฉ๊ณผ ๊ด€๋ จ๋œ ์ƒํƒœ ๊ฐœ์ฒด), unused(๋Œ€๋ถ€๋ถ„์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ˜„์žฌ ๋ฌด์‹œ๋˜๋Š” ์ƒˆ ํ•ญ๋ชฉ์˜ ์ œ๋ชฉ) ๋ฐ url(์ƒˆ URL)์˜ ์„ธ ๊ฐ€์ง€ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • replaceState(): ํ˜„์žฌ ๊ธฐ๋ก ํ•ญ๋ชฉ์„ ์ƒˆ ํ•ญ๋ชฉ์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. pushState()์™€ ๋™์ผํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์ƒˆ ํ•ญ๋ชฉ์„ ๋งŒ๋“œ๋Š” ๋Œ€์‹  ํ˜„์žฌ ํ•ญ๋ชฉ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  1. ์ฝ๊ธฐ ๊ธฐ๋ก(Reading History): ๊ธฐ๋ก ๊ฐœ์ฒด๋Š” ๊ฒ€์ƒ‰ ๊ธฐ๋ก์— ๋Œ€ํ•œ ์ •๋ณด์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ผ๋ถ€ ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • length: ํžˆ์Šคํ† ๋ฆฌ ์Šคํƒ์˜ ํ•ญ๋ชฉ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • state: ํ˜„์žฌ ๊ธฐ๋ก ํ•ญ๋ชฉ๊ณผ ๊ด€๋ จ๋œ ์ƒํƒœ ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  1. ๋‚ด๋น„๊ฒŒ์ด์…˜ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ(Handling Navigation Events): History API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฑฐ๋‚˜ URL์ด ๋ณ€๊ฒฝ๋  ๋•Œ์™€ ๊ฐ™์€ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. PopStateEvent๋Š” ์‚ฌ์šฉ์ž๊ฐ€ go(), back() ๋˜๋Š” forward()์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ก์„ ํƒ์ƒ‰ํ•  ๋•Œ ํŠธ๋ฆฌ๊ฑฐ๋œ๋‹ค. ์ด ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ๊ทธ์— ๋”ฐ๋ผ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. URL ์กฐ์ž‘(Manipulating URLs): History API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋กœ๋“œํ•˜์ง€ ์•Š๊ณ ๋„ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ ํ‘œ์‹œ์ค„์— ํ‘œ์‹œ๋œ URL์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•ž์—์„œ ์–ธ๊ธ‰ํ•œ pushState() ๋ฐ replaceState() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋กœ๋“œํ•˜์ง€ ์•Š๊ณ ๋„ URL์„ ๋ณ€๊ฒฝํ•˜๊ณ  ๊ธฐ๋ก ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€/์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.

  3. ํ˜ธํ™˜์„ฑ ๋ฐ ์ œํ•œ(Compatibility and Limitations): History API๋Š” ์ตœ์‹  ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ์ธํ•ด ๋ช‡ ๊ฐ€์ง€ ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ ์ฃผ์†Œ ํ‘œ์‹œ์ค„์—์„œ ์ „์ฒด URL์„ ์ง์ ‘ ์ฝ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค. URL ๊ฒฝ๋กœ, ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐ ์กฐ๊ฐ๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

React Router์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ œ๊ณตํ•œ๋‹ค

  • Link: HTML์˜ a ํƒœ๊ทธ์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ ํŽ˜์ด์ง€ ์ „ํ™˜์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ๋‹ค.

  • NavLink: Link์˜ ํŠน์ˆ˜ ๋ฒ„์ „์œผ๋กœ, ํŠน์ • ๋งํฌ์— ์Šคํƒ€์ผ์„ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

  • Navigate: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

  • useNavigate: ํŽ˜์ด์ง€ ์ด๋™์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ›…์ด๋‹ค.

Link์™€ NavLink๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค:

import { Link, NavLink } from "react-router-dom";

<Link to="/about">About</Link>
declare function Link(props: LinkProps): React.ReactElement;

interface LinkProps
  extends Omit<
    React.AnchorHTMLAttributes<HTMLAnchorElement>,
    "href"
  > {
  replace?: boolean;
  state?: any;
  to: To;
  reloadDocument?: boolean;
  preventScrollReset?: boolean;
  relative?: "route" | "path";
}

type To = string | Partial<Path>;

interface Path {
  pathname: string;
  search: string;
  hash: string;
}
import { NavLink } from "react-router-dom";
<NavLink
  to={path}
  className={({ isActive, isPending }) =>
    isPending ? "pending" : isActive ? "active" : ""
  }
  style={({ isActive, isPending }) => {
    return {
      fontWeight: isActive ? "bold" : "",
      color: isPending ? "red" : "black",
    };
  }}
  >
  {({ isActive }) => (<SubItem id={sub.id} className={`${sub.id}${isActive ? ' active' : ''}`}>{sub.titleName}</SubItem>)}
</NavLink>
export interface NavLinkProps extends Omit<LinkProps, "className" | "style" | "children"> {
    children?: React.ReactNode | ((props: {
        isActive: boolean;
        isPending: boolean;
    }) => React.ReactNode);
    caseSensitive?: boolean;
    className?: string | ((props: {
        isActive: boolean;
        isPending: boolean;
    }) => string | undefined);
    end?: boolean;
    style?: React.CSSProperties | ((props: {
        isActive: boolean;
        isPending: boolean;
    }) => React.CSSProperties | undefined);
}

Navigate์™€ useNavigate๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค

import { Navigate, useNavigate } from "react-router-dom";

<Navigate to="/about" />
const navigate = useNavigate();
navigate("/about");

Last updated