Home react-router-dom v7
Post
X

react-router-dom v7

React Router v7

React Router는 React 전용 클라이언트 라우팅 라이브러리입니다.

SPA(Single Page Application) 방식에서도 URL 기반 네비게이션을 가능하게 하여 사용자 경험을 향상시킵니다.

기존 버전보다 더 단순해지고, 데이터 중심 구조와 UX 향상을 위한 다양한 기능이 추가되었습니다.


주요 특징

  • 빨라진 라우팅 성능

    partial rendering 지원 unnecessary re-render 감소 Vite + React 19 환경과 최적화 궁합

  • 단순해진 API

    Routes, Route, Navigate, Outlet 중심으로 정리 중첩 라우트가 이전보다 명확해짐

  • 데이터 중심 구조 지원 강화

    loader / action 등(v7.3+)에서 서버 중심 구조를 도입 서버 액션을 통한 Form 관리 가능

  • File Router 공식 도입

    Next.js App Router와 비슷한 파일 기반 라우팅 자동 코드 스플리팅, Lazy loading

  • TypeScript 개선

    라우트 객체 기반 정의 지원


React Router v7의 핵심 개념 변화

React Router v7은 컴포넌트 라우터가 아니라 데이터 라우터

1
2
3
4
5
6
7
// v6
<Routes>
  <Route path="/" element={<Home />} />
</Routes>;

// v7
createBrowserRouter([{ path: "/", element: <Home /> }]);

Router 설정 (routes/index.jsx)

  • 객체 기반 라우팅
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { createBrowserRouter } from "react-router-dom";
import MainLayout from "./layouts";
import Home from "@/pages/Home";
import Login from "@/pages/Login";
import NotFound from "@/pages/NotFound";

export const router = createBrowserRouter([
  {
    element: <MainLayout />,
    children: [
      {
        path: "/",
        element: <Home />,
      },
      {
        path: "/login",
        element: <Login />,
      },
    ],
  },
  {
    path: "*",
    element: <NotFound />,
  },
]);

Layout + Outlet 개념 (routes/layouts.jsx)

  • Layout : 공통 UI
  • Outlet : 하위 라우트 렌더링 위치
1
2
3
4
5
6
7
8
9
10
11
import { Outlet } from "react-router-dom";
import Header from "@/components/Header";

export default function MainLayout() {
  return (
    <>
      <Header />
      <Outlet />
    </>
  );
}

페이지 이동

1
2
3
4
5
6
// 선언적 이동 : <Link> 사용
<Link to="/about">About</Link>;

// 명령형 이동 : useNavigate() 사용
const navigate = useNavigate();
navigate("/about");

URL 파라미터

  • 라우트 객체에서 선언
  • loader와 컴포넌트에서 모두 접근 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 라우트 정의
{
  path: "/users/:userId",
  element: <UserDetail />,
  loader: userLoader,
}

// loader에서 접근
// URL 파라미터는 무조건 loader에서 먼저 처리하는 게 실무 표준
export async function userLoader({ params }) {
  const { userId } = params;

  const res = await fetch(`/api/users/${userId}`);
  return res.json();
}

// 컴포넌트에서 접근
import { useLoaderData, useParams } from "react-router-dom";

export default function UserDetail() {
  const user = useLoaderData();
  const { userId } = useParams();

  return (
    <div>
      <h1>User {userId}</h1>
      <p>{user.name}</p>
    </div>
  );
}

중첩 라우트 (Nested Routes)

  • 파라미터는 자동으로 상속
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/dashboard
/dashboard/profile
/dashboard/settings

// 라우트 정의
{
  path: "/dashboard",
  element: <DashboardLayout />,
  loader: dashboardGuard,
  children: [
    // index route
    // /dashboard 진입 시 기본 화면
    {
      index: true,
      element: <DashboardHome />,
    },
    // /dashboard/profile
    {
      path: "profile",
      element: <Profile />,
      loader: profileLoader,
    },
    // /dashboard/settings
    {
      path: "settings",
      element: <Settings />,
    },
  ],
}

Layout + Outlet

1
2
3
4
5
6
7
8
9
10
11
12
import { Outlet } from "react-router-dom";

export default function DashboardLayout() {
  return (
    <div>
      <Sidebar />
      <main>
        <Outlet />
      </main>
    </div>
  );
}

errorElement – 에러 처리

  • 라우트 단위 에러 처리
1
2
3
4
5
{
  path: "/",
  element: <Home />,
  errorElement: <ErrorPage />,
}

인증 Guard (실무 핵심)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export async function authLoader() {
  const isLoggedIn = false;

  if (!isLoggedIn) {
    throw redirect("/login");
  }

  return null;
}

{
  element: <MainLayout />,
  loader: authLoader,
  children: [...],
}

Redirect (리다이렉트)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 컴포넌트 기반
import { Navigate } from "react-router-dom";

return <Navigate to="/login" replace />;

// 라우트 로직 기반 (권장)
import { redirect } from "react-router-dom";

export async function loader() {
  const isLoggedIn = false;

  if (!isLoggedIn) {
    throw redirect("/login");
  }

  return null;
}

Data Fetch – 라우트 단위 데이터 로딩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export async function homeLoader() {
  const res = await fetch("/api/home");
  return res.json();
}

{
  path: "/",
  element: <Home />,
  loader: homeLoader,
}

// 페이지에서 사용 시
import { useLoaderData } from "react-router-dom";

export default function Home() {
  const data = useLoaderData();
  return <div>{data.title}</div>;
}

v7에서 loader

Route에 진입할 때 컴포넌트 렌더링 전에 실행되는 비동기 함수로 다양한 역할을 수행합니다.

  • 서버 데이터 조회
  • 인증 / 권한 체크 (Guard)
  • redirect 판단
  • 에러 throw

또한,

  • 반환 값은 useLoaderData()로 접근
  • redirect() / throw new Response() 가능
  • URL params, search params 접근 가능

즉, Guard + Redirect + Data Fetch를 하나의 진입 파이프라인에서 처리합니다.


기본 동작 흐름

1
2
3
4
5
6
7
8
URL 접근
  
해당 route의 loader 실행
  
(조건 판단)
  ├─ redirect 발생  즉시 이동
  ├─ error throw  errorElement 렌더
  └─ 정상  element 렌더 + data 전달

action

HTTP의 POST / PUT / PATCH / DELETE에 대응하는 라우트 함수입니다.


기본 동작 흐름

1
2
3
4
5
6
7
8
9
10
11
12
사용자가 <Form method="post"> 제출
  
해당 route의 action 실행
  
action 내부에서 서버 API 호출
  
(조건 판단)
  ├─ redirect()
  ├─ JSON 반환
  └─ 에러 throw
  
관련 loader 자동 revalidation

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.