(부록) BrowserRouter 방식
본 챕터는 React Router v6의 기존 방식인 BrowserRouter를 다룹니다. 이 방식은 v6.4 이전부터 사용되어 왔으며, 많은 기존 프로젝트에서 여전히 사용되고 있습니다. 레거시 코드를 이해하거나 유지보수해야 할 때 참고하시기 바랍니다.
새로운 프로젝트에서는 createBrowserRouter와 RouterProvider를 사용하는 것을 권장합니다.
1. BrowserRouter, Routes, Route
기존 방식에서는 BrowserRouter, Routes, Route 세 가지 컴포넌트를 조합하여 라우팅을 구현합니다.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/one" element={<One />} />
<Route path="/two" element={<Two />} />
<Route path="/three" element={<Three />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>home</h1>;
}
function One() {
return <h1>one</h1>;
}
function Two() {
return <h1>two</h1>;
}
function Three() {
return <h1>three</h1>;
}
export default App;
이제 접속하는 URL에 따라 해당하는 화면(컴포넌트)이 바뀌는 걸 확인해보겠습니다. 프로젝트를 시작하면 첫 화면에서 "home"이라는 문구가 화면에 표시됩니다. 이제 주소창의 URL 뒤에 /one을 붙여 이동해보겠습니다. 이번에는 "one"이라는 문구가 화면에 표시됩니다.
위 코드에서는 React Router DOM 라이브러리의 BrowserRouter, Routes, Route 세 가지 주요 컴포넌트를 사용하였습니다.
- BrowserRouter 컴포넌트 : 브라우저 주소창의 URL이 변경될 때마다 이를 감지하고 현재 위치를 저장합니다. URL과 UI를 연결하여 주소가 바뀌면 해당하는 화면(컴포넌트)을 보여줍니다. 또한 브라우저의 뒤로 가기, 앞으로 가기 기능을 지원합니다.
- Routes 컴포넌트 : 여러 Route 컴포넌트를 감싸는 상위 컴포넌트로, URL이 변경되면 하위의 모든 Route 컴포넌트 중 현재 주소와 일치하는 Route를 찾아 렌더링합니다.
- Route 컴포넌트 : 현재 URL에 맞는 UI를 렌더링하는 역할을 합니다. path 속성에는 경로를, element 속성에는 해당 경로와 매칭할 컴포넌트를 작성하여 특정 URL 경로에 어떤 컴포넌트를 보여줄지 지정합니다.
2. Link 컴포넌트
Link 컴포넌트는 클릭하면 다른 경로로 이동하는 링크를 생성합니다. 이때 주소는 바뀌지만, 페이지를 새로 불러오진 않습니다.
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Link to="/">home</Link>
<Link to="/one">one</Link>
<Link to="/two">two</Link>
<Link to="/three">three</Link>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/one" element={<One name="react" />} />
<Route path="/two" element={<Two />} />
<Route path="/three" element={<Three />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>home</h1>;
}
function One({ name }) {
return <h1>{name} world</h1>;
}
function Two() {
return <h1>two</h1>;
}
function Three() {
return <h1>three</h1>;
}
export default App;
3. 중첩 라우팅
BrowserRouter 방식에서도 중첩 라우팅을 구현할 수 있습니다.
import { BrowserRouter, Routes, Route, Link, Outlet } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="main" element={<MainContent />} />
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
</BrowserRouter>
);
}
function Dashboard() {
return (
<div>
<h1>대시보드</h1>
<nav>
<Link to="/dashboard/main">홈</Link>
<Link to="/dashboard/settings">설정</Link>
<Link to="/dashboard/profile">프로필</Link>
</nav>
{/* 자식 라우트가 이 위치에 렌더링됩니다 */}
<Outlet />
</div>
);
}
function MainContent() {
return <p>메인 내용</p>;
}
function Settings() {
return <p>설정창</p>;
}
function Profile() {
return <p>유저프로필</p>;
}
export default App;
4. URL 파라미터
동적 라우팅을 위한 URL 파라미터 사용법은 동일합니다.
import {
BrowserRouter,
Routes,
Route,
Link,
useParams,
} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">home</Link>
<Link to="/blog/1">blog_1</Link>
<Link to="/blog/2">blog_2</Link>
<Link to="/blog/3">blog_3</Link>
</nav>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/blog/:id" element={<Blog />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>home</h1>;
}
function Blog() {
const { id } = useParams();
return <h1>Blog Post {id}</h1>;
}
export default App;
5. 404 페이지
존재하지 않는 경로를 처리하는 방법도 동일합니다.
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">홈</Link>
<Link to="/about">소개</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
function Home() {
return <h1>홈</h1>;
}
function About() {
return <h1>소개</h1>;
}
function NotFound() {
return (
<div>
<h1>404 - 페이지를 찾을 수 없습니다</h1>
<Link to="/">홈으로 돌아가기</Link>
</div>
);
}
export default App;
6. BrowserRouter vs createBrowserRouter 비교
| 특성 | BrowserRouter | createBrowserRouter |
|---|---|---|
| 라우트 정의 | JSX 기반 | 객체 기반 |
| 데이터 로딩 | useEffect 사용 | loader 함수 |
| 에러 처리 | 컴포넌트 내부에서 처리 | errorElement |
| 로딩 상태 | useState로 직접 관리 | useNavigation |
| 코드 구조 | 컴포넌트에 로직 집중 | 라우트에 로직 분리 |
어떤 방식을 선택해야 할까요?
- 새 프로젝트:
createBrowserRouter사용을 권장합니다. 데이터 로딩과 에러 처리가 더 체계적입니다. - 기존 프로젝트: 기존
BrowserRouter방식을 유지해도 됩니다. 필요에 따라 점진적으로 마이그레이션할 수 있습니다. - 학습 목적: 두 방식 모두 이해하는 것이 좋습니다. 실무에서 다양한 코드베이스를 만날 수 있습니다.