react-router-dom을 사용해서 라우팅을 구현하려고 할 때, 대표적으로 두 가지 방법이 있다.
BrowserRouter을 사용하는 방식과, createBrowserRouter을 사용하는 방식이 있다.
이번 포스트에서는 이 둘의 차이점과 어떤 걸 사용해야 좋을지 알아보자.
BrowserRouter 방식은 초기 React Router부터 사용된 방식이다.
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router";
import App from "./app";
const root = document.getElementById("root");
ReactDOM.createRoot(root).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
</Routes>
</BrowserRouter>,
);
이런식으로 <BrowserRouter> 과 <Routes>로 감싸주어야 라우팅이 가능하다.
렌더할 때는 어플리케이션을 <BrowserRouter>로 감싸주면 된다.
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router";
import App from "./app";
const root = document.getElementById("root");
ReactDOM.createRoot(root).render(
<BrowserRouter>
<App />
</BrowserRouter>,
);
이런식으로 경로를 중첩시키는 것도 가능하다.
<Routes>
<Route path="dashboard" element={<Dashboard />}>
<Route index element={<Home />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
"dashboard/settings"
createBrowserRouter는 비교적 최신 방법이다. React Router v6.4에서 도입됐다.
차이점으로는 라우트 정의를 컴포넌트가 아닌 자바스크립트 객체로 분리하여 생성한다.
추가 기능으로
loader(렌더링 전 데이터 로딩), action(폼 제출 처리)errorElement를 지정해서 NotFound 페이지를 처리할 수 있다.import { createBrowserRouter } from "react-router";
function Root() {
return <h1>Hello world</h1>;
}
const router = createBrowserRouter([
{ path: "/", Component: Root },
]);
이런식으로 createBrowserRouter을 사용할 수 있고,
라우팅은 아래처럼 하면 된다.
createBrowserRouter([
{
path: "/",
Component: Root,
children: [
{ index: true, Component: Home },
{ path: "about", Component: About },
{
path: "auth",
Component: AuthLayout,
children: [
{ path: "login", Component: Login },
{ path: "register", Component: Register },
],
},
{
path: "concerts",
children: [
{ index: true, Component: ConcertsHome },
{ path: ":city", Component: ConcertsCity },
{ path: "trending", Component: ConcertsTrending },
],
},
],
},
]);
children을 이용해서 중첩 라우팅도 할 수 있다.
렌더할 때는 RouterProvider에 router를 전달해주면 된다.
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter } from "react-router";
import { RouterProvider } from "react-router/dom";
const router = createBrowserRouter([
{
path: "/",
element: <div>Hello World</div>,
},
]);
const root = document.getElementById("root");
ReactDOM.createRoot(root).render(
<RouterProvider router={router} />,
);
위에서 말한 것 처럼 data loading이나 actions를 사용할 수 있다. 아래는 loader에 대한 예제다
import {
createBrowserRouter,
useLoaderData,
} from "react-router";
createBrowserRouter([
{
path: "/teams/:teamId",
loader: async ({ params }) => {
let team = await fetchTeam(params.teamId);
return { name: team.name };
},
Component: Team,
},
]);
function Team() {
let data = useLoaderData();
return <h1>{data.name}</h1>;
}
그러면 어떤 걸 써야 할까?
createBrowserRouter을 사용하는 게 좋다.
사실 v6.4 이전부터 사용하고 있었던 BrowserRouter을 지원해주는 것이지, 공식문서에서도 createBrowserRouter을 권장하고 있다.
데이터 로딩과, 액션과 같은 추가 기능 뿐만 아니라, 객체로 관리하기 때문에, 복잡한 라우팅을 쉽게 관리할 수 있다.
그리고 라우팅 중 오류가 생겼을 때도 errorElement를 이용해 쉽게 에러 처리를 할 수 있다.
사실 공식문서에는 이 두가지 외에도 프레임워크 모드라는 새로운 방식도 소개하고 있다.
와 같은 상황이 있을 때 프레임워크 모드를 사용하라고 하기도 한다..
각자 상황에 맞는 걸 알맞게 사용하면 될듯 하다..
다만 이번 블로그의 주제에 맞게 말하자면, BrowserRouter을 사용하기 보다는 createBrowserRouter을 사용해보는 건 어떨까?