2 분 소요

개요

React Router는 React 앱에서 클라이언트 사이드 라우팅을 제공하는 라이브러리입니다. 페이지 이동 시 서버에 요청하지 않고 JavaScript로 화면을 전환합니다.


설치

npm install react-router-dom


기본 구성

폴더 구조

src/
├── App.tsx
└── pages/
    ├── Home.tsx
    ├── About.tsx
    └── Users.tsx

페이지 컴포넌트 작성

// src/pages/Home.tsx
function Home() {
  return <h1>홈 페이지</h1>;
}
export default Home;

// src/pages/About.tsx
function About() {
  return <h1>소개 페이지</h1>;
}
export default About;

// src/pages/Users.tsx
function Users() {
  return <h1>사용자 목록</h1>;
}
export default Users;

라우터 설정

// src/App.tsx
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Users from "./pages/Users";

function App() {
  return (
    <BrowserRouter>
      {/* 네비게이션 - <a> 대신 <Link> 사용 (페이지 새로고침 방지) */}
      <nav>
        <Link to="/"></Link>
        <Link to="/about">소개</Link>
        <Link to="/users">사용자</Link>
      </nav>

      {/* 현재 URL에 맞는 컴포넌트 렌더링 */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/users" element={<Users />} />
        <Route path="*" element={<p>404 - 페이지를 찾을 수 없습니다</p>} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;


URL 파라미터

동적 URL에서 값을 추출합니다.

// 라우트 정의
<Route path="/users/:id" element={<UserDetail />} />

// src/pages/UserDetail.tsx
import { useParams } from "react-router-dom";
import { useState, useEffect } from "react";

function UserDetail() {
  const { id } = useParams<{ id: string }>();   // URL의 :id 추출
  const [user, setUser] = useState<{ name: string; email: string } | null>(null);

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
      .then((res) => res.json())
      .then((data) => setUser(data));
  }, [id]);

  return (
    <div>
      <h1>사용자 상세</h1>
      {user ? (
        <div>
          <p>이름: {user.name}</p>
          <p>이메일: {user.email}</p>
        </div>
      ) : (
        <p>로딩 중...</p>
      )}
    </div>
  );
}

export default UserDetail;
// 링크에서 파라미터 포함
import { Link } from "react-router-dom";

function Users() {
  const users = [
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
  ];

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>
          <Link to={`/users/${user.id}`}>{user.name}</Link>
        </li>
      ))}
    </ul>
  );
}


Query String (쿼리 파라미터)

URL의 ?key=value 형태의 파라미터를 다룹니다.

// URL 예: /search?q=react&page=2

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

function Search() {
  const [searchParams, setSearchParams] = useSearchParams();

  const query = searchParams.get("q") ?? "";         // null이면 ""
  const page = Number(searchParams.get("page")) || 1;

  return (
    <div>
      <input
        value={query}
        onChange={(e) => setSearchParams({ q: e.target.value, page: "1" })}
        placeholder="검색어 입력"
      />
      <p>검색어: {query}, 페이지: {page}</p>
    </div>
  );
}


코드로 페이지 이동 (useNavigate)

버튼 클릭이나 로직 처리 후 특정 페이지로 이동합니다.

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

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

  const handleLogin = async () => {
    // 로그인 처리 후 메인으로 이동
    await login();
    navigate("/");           // 특정 경로로 이동
    navigate(-1);            // 뒤로 가기
    navigate(1);             // 앞으로 가기
    navigate("/login", { replace: true });  // 이력 교체 (뒤로 가기 불가)
  };

  return <button onClick={handleLogin}>로그인</button>;
}


NavLink (활성 링크 스타일)

현재 URL과 일치하는 링크에 자동으로 스타일을 적용합니다.

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

function Nav() {
  return (
    <nav>
      <NavLink
        to="/"
        style={({ isActive }) => ({ fontWeight: isActive ? "bold" : "normal" })}
      ></NavLink>
      <NavLink
        to="/about"
        className={({ isActive }) => isActive ? "active-link" : ""}
      >
        소개
      </NavLink>
    </nav>
  );
}


중첩 라우트 (Nested Routes)

레이아웃을 공유하는 중첩 구조를 만듭니다.

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

// 공통 레이아웃
function Layout() {
  return (
    <div>
      <header>공통 헤더</header>
      <Outlet />    {/* 하위 라우트가 여기에 렌더링 */}
      <footer>공통 푸터</footer>
    </div>
  );
}

// 라우트 설정
<Routes>
  <Route path="/" element={<Layout />}>
    <Route index element={<Home />} />           {/* 경로: / */}
    <Route path="about" element={<About />} />   {/* 경로: /about */}
    <Route path="users" element={<Users />} />   {/* 경로: /users */}
  </Route>
</Routes>


관련 링크