็„ก์ œ

React Router (react-router-dom) ๋ณธ๋ฌธ

<React>

React Router (react-router-dom)

yo-u-loo 2026. 7. 14. 12:49

 

๐ŸŸก React Router (react-router-dom)

React Router๋Š” React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์šฐํŒ…(Client-side Routing)์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

react-router-dom์€ ์ด๋ฅผ ์›น ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜๋Š” ํŒจํ‚ค์ง€.

 

โ—ผ๏ธ ์ฃผ์š” ํŠน์ง•

1๏ธโƒฃ URL์— ๋”ฐ๋ฅธ ํ™”๋ฉด ๋ Œ๋”๋ง (Routing)

URL ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ์„œ๋กœ ๋‹ค๋ฅธ React ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

<Route path="/about" element={<About />} />
<Route path="/products" element={<Products />} />
  • ์˜ˆ๋ฅผ ๋“ค์–ด /about, /products์™€ ๊ฐ™์€ ๊ฒฝ๋กœ์— ์ ‘๊ทผํ•˜๋ฉด ์„ค์ •๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

 

2๏ธโƒฃ ๋™์  URL ์ฒ˜๋ฆฌ (URL Parameters)

URL์— ๊ฐ’์„ ํฌํ•จํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

<Route path="/products/:id" element={<ProductDetail />} />

/products/1
/products/2
/products/3
  • :id๋Š” ๋™์  URL ํŒŒ๋ผ๋ฏธํ„ฐ์ด๋ฉฐ, useParams()๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
    • ์˜ˆ: const { id } = useParams();

 

3๏ธโƒฃ ํŽ˜์ด์ง€ ์ด๋™ (Navigation)

ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • <Link> ์ปดํฌ๋„ŒํŠธ: HTML์˜ <a> ํƒœ๊ทธ์ฒ˜๋Ÿผ ์ด๋™ํ•˜๋ฉด์„œ๋„ SPA ๋ฐฉ์‹์˜ ๋น ๋ฅธ ํ™”๋ฉด ์ „ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

4๏ธโƒฃ ์ค‘์ฒฉ ๋ผ์šฐํŒ… (Nested Routing)

๋ถ€๋ชจ ๋ผ์šฐํŠธ ์•ˆ์— ์ž์‹ ๋ผ์šฐํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ ๋ณต์žกํ•œ ํ™”๋ฉด ๊ตฌ์กฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด /dashboard/profile์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€ ๋‚ด๋ถ€์—์„œ ์—ฌ๋Ÿฌ ํ•˜์œ„ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

Outlet์„ ํ†ตํ•ด ์ค‘์ฒฉ๋œ ๋ผ์šฐํŠธ์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋œ๋‹ค.

 

โ—ผ๏ธ ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ

๐Ÿ”น BrowserRouter

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด๋ฅผ ๊ฐ์‹ธ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ผ์šฐํ„ฐ์ด๋‹ค.

HTML5 History API(pushState, replaceState)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ URL์„ ๋ณ€๊ฒฝํ•˜๊ณ , ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š๊ณ ๋„ ํ™”๋ฉด์„ ์ „ํ™˜ํ•˜๋ฉฐ ๋ธŒ๋ผ์šฐ์ €์˜ ๋’ค๋กœ๊ฐ€๊ธฐ·์•ž์œผ๋กœ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค.

import { BrowserRouter } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      {/* ๋ผ์šฐํŒ… ๊ด€๋ จ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์—ฌ๊ธฐ์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค */}
    </BrowserRouter>
  );
}

 

๐Ÿ”น Routes / Route

Routes๋Š” ์—ฌ๋Ÿฌ Route๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ํ˜„์žฌ URL๊ณผ ์ผ์น˜ํ•˜๋Š” Route๋ฅผ ์ฐพ์•„ ํ•ด๋‹น Route์˜ element๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

Route๋Š” ํŠน์ • URL ๊ฒฝ๋กœ์™€ ๋ Œ๋”๋งํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค. 

import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/contact" element={<Contact />} />
    </Routes>
  );
}

 

๐Ÿ”น Link

์ผ๋ฐ˜์ ์ธ <a> ํƒœ๊ทธ์ฒ˜๋Ÿผ ์ด๋™ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, React Router๊ฐ€ URL์„ ๋ณ€๊ฒฝํ•˜๊ณ  ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ ํŽ˜์ด์ง€ ์ „์ฒด๊ฐ€ ์ƒˆ๋กœ๊ณ ์นจ๋˜์ง€ ์•Š๋Š”๋‹ค.

import { Link } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <Link to="/">ํ™ˆ</Link>
      <Link to="/about">์†Œ๊ฐœ</Link>
      <Link to="/contact">์—ฐ๋ฝ์ฒ˜</Link>
    </nav>
  );
}

 

๐Ÿ”น NavLink

๋‚ด๋ถ€์ ์œผ๋กœ Link๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ํ˜„์žฌ URL๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ isActive ๊ฐ’์„ ์ œ๊ณตํ•œ๋‹ค.

์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ™œ์„ฑ ๋ฉ”๋‰ด ์Šคํƒ€์ผ์„ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

import { NavLink } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <NavLink 
        to="/" 
        style={({ isActive }) => isActive ? { color: 'red' } : undefined}
      >
        ํ™ˆ
      </NavLink>
      <NavLink 
        to="/about"
        className={({ isActive }) => isActive ? 'active-link' : ''}
      >
        ์†Œ๊ฐœ
      </NavLink>
    </nav>
  );
}

 

๐Ÿ”น HashRouter (์„ ํƒ)

URL์— #์„ ํฌํ•จํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„์˜ ๋ณ„๋„ ๋ผ์šฐํŒ… ์„ค์ •์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

์„œ๋ฒ„์—์„œ URL ์žฌ์ž‘์„ฑ(Rewrite) ์„ค์ •์„ ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ด๋ผ๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ BrowserRouter ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋œ๋‹ค.

import { HashRouter } from 'react-router-dom';

function App() {
  return (
    <HashRouter>
      {/* ๋ผ์šฐํŒ… ๊ด€๋ จ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์—ฌ๊ธฐ์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค */}
    </HashRouter>
  );
}
  • BrowserRouter: https://example.com/about
  • HashRouter: https://example.com/#/about

 

๐Ÿ”น Outlet

๋ถ€๋ชจ ๋ผ์šฐํŠธ์—์„œ ์ค‘์ฒฉ๋œ(์ž์‹) ๋ผ์šฐํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ์œ„์น˜๋ฅผ ์ง€์ •ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

๊ณตํ†ต ๋ ˆ์ด์•„์›ƒ(Header, Sidebar ๋“ฑ)์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋‚ด๋ถ€ ํ™”๋ฉด๋งŒ ๋ณ€๊ฒฝํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

function App() {
  return (
    <Routes>
      <Route path="/dashboard" element={<DashboardLayout />}>
        {/* ์ค‘์ฒฉ๋œ ๋ผ์šฐํŠธ๋“ค */}
        <Route index element={<DashboardHome />} />
        <Route path="profile" element={<Profile />} />
        <Route path="settings" element={<Settings />} />
      </Route>
    </Routes>
  );
}

// Dashboard ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ Outlet์„ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘์ฒฉ ๋ผ์šฐํŠธ ๋ Œ๋”๋ง
function Dashboard() {
  return (
    <div>
      <h1>๋Œ€์‹œ๋ณด๋“œ</h1>
      <nav>
        <Link to="/dashboard">ํ™ˆ</Link>
        <Link to="/dashboard/profile">ํ”„๋กœํ•„</Link>
        <Link to="/dashboard/settings">์„ค์ •</Link>
      </nav>
      <Outlet /> {/* ์ค‘์ฒฉ๋œ ๋ผ์šฐํŠธ๊ฐ€ ์—ฌ๊ธฐ์— ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค */}
    </div>
  );
}

 

๐Ÿ”น useNavigate (ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹ ์ด๋™)

์‚ฌ์šฉ์ž์˜ ์ด๋ฒคํŠธ๋‚˜ ํŠน์ • ๋กœ์ง ์‹คํ–‰ ํ›„ ์›ํ•˜๋Š” ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

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

function Login() {
  const navigate = useNavigate();

  const handleLogin = () => {
    // ๋กœ๊ทธ์ธ ์„ฑ๊ณต
    navigate("/dashboard");
  };

  return (
    <button onClick={handleLogin}>
      ๋กœ๊ทธ์ธ
    </button>
  );
}
  • useNavigate๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ ํ›„ ์ฝ”๋“œ์—์„œ ์›ํ•˜๋Š” ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

 

๐Ÿ”น useParams (๋™์  URL ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ)

Route์—์„œ ์ •์˜ํ•œ URL ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

import { useParams } from "react-router-dom";

function ProductDetail() {
  const { id } = useParams();

  return (
    <h1>
      ์ƒํ’ˆ ๋ฒˆํ˜ธ : {id}
    </h1>
  );
}

/* URL - /products/10, ๊ฒฐ๊ณผ - ์ƒํ’ˆ ๋ฒˆํ˜ธ : 10 */
  • useParams() ์‚ฌ์šฉ ์ˆœ์„œ:
    1. useParams๋ฅผ importํ•œ๋‹ค.
    2. useParams()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค.
    3. Route์˜ path์— /:๋ณ€์ˆ˜๋ช…์„ ์ž‘์„ฑํ•œ๋‹ค.
    4. ์ €์žฅํ•œ ๋ณ€์ˆ˜๋ฅผ ์›ํ•˜๋Š” ๊ณณ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

๐ŸŒŸ ํŒ: 404 ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€ ๐ŸŒŸ

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="*" element={<NotFound />} />
</Routes>
  • * ๊ฒฝ๋กœ๋Š” ์ •์˜๋˜์ง€ ์•Š์€ ๋ชจ๋“  URL์„ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ Not Found ํŽ˜์ด์ง€ ๊ตฌํ˜„์— ์‚ฌ์šฉํ•œ๋‹ค.
    • ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ฑฐ์˜ ํ•„์ˆ˜.
    • ๋ฐ˜๋“œ์‹œ ๋งˆ์ง€๋ง‰์— ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ .

 

 

๐Ÿ“‹ React Router DOM ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ ๐Ÿ“‹

์ปดํฌ๋„ŒํŠธ ์—ญํ• 
BrowserRouter History API ๊ธฐ๋ฐ˜์œผ๋กœ URL๊ณผ UI๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ธฐ๋ณธ ๋ผ์šฐํ„ฐ
Routes ํ˜„์žฌ URL๊ณผ ์ผ์น˜ํ•˜๋Š” Route๋ฅผ ๊ด€๋ฆฌ
Route URL ๊ฒฝ๋กœ์™€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐ
Link ์ƒˆ๋กœ๊ณ ์นจ ์—†์ด ํŽ˜์ด์ง€ ์ด๋™
NavLink ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ๋งํฌ์— ์Šคํƒ€์ผ ์ ์šฉ
Outlet ์ค‘์ฒฉ ๋ผ์šฐํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ์œ„์น˜
HashRouter # ๊ธฐ๋ฐ˜์œผ๋กœ ๋ผ์šฐํŒ…ํ•˜๋ฉฐ ์ •์  ํ˜ธ์ŠคํŒ… ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ

 

๐Ÿ“‹ Hooks ์ฃผ์š” API ๐Ÿ“‹

API ์—ญํ• 
useParams URL ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
useNavigate ์ฝ”๋“œ๋กœ ํŽ˜์ด์ง€ ์ด๋™
useLocation ํ˜„์žฌ URL ์ •๋ณด ํ™•์ธ
useSearchParams Query String ๊ด€๋ฆฌ
useOutletContext
๋ถ€๋ชจ Outlet์—์„œ ์ „๋‹ฌํ•œ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ

 


 

๐Ÿ”— React Router DOM ์„ค์น˜ ๋ฐฉ๋ฒ• ๐Ÿ”—

https://reactrouter.com/

 

https://reactrouter.com/tutorials/quickstart

 

terminal

npm install react-router-dom

 

https://reactrouter.com/api/components/Link

 

https://reactrouter.com/api/components/Links

 

https://reactrouter.com/api/components/NavLink

 

https://reactrouter.com/api/components/Route

 

https://reactrouter.com/api/components/Routes

 

https://reactrouter.com/api/hooks/useParams