리액트로 만들어진 웹 앱은 싱글 페이지 애플리케이션(Single Page Application, SPA)이다. 즉, 하나의 페이지에서 내용을 동적으로 변경하는 웹 앱이라는 것이다. 하지만 번개 모입 웹 앱에서는 글 목록, 글 쓰기, 마이페이지 등 여러 페이지가 필요하며 각각의 화면마다 url 주소도 달라져야 한다. 주소에 따라 다른 화면을 보여주는 것을 라우팅이라고 하는데 리액트는 라우팅 기능을 내장하고 있지 않다.
그래서 이번 프로젝트에는 리액트 프로젝트에서 가장 많이 사용되는 라우팅 라이브러리인 react-router
를 설치해 사용할 것이다.
npm i react-router-dom
src/app.js
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import BungaeMainPage from "./pages/BunageMain";
import BungaeDetailPage from "./pages/BungaeDetail";
import BungaeSearchPage from "./pages/BungaeSearch";
import CreateBungaePage from "./pages/CreateBungae";
import EditBungaePage from "./pages/EditBungae";
import EmailAuthPage from "./pages/EmailAuth";
import ErrorPage from "./pages/Error";
import LoginPage from "./pages/Login";
import ModifyUserInfoPage from "./pages/ModifyUserInfo";
import ProfilePage from "./pages/Profile";
import RootLayout from "./pages/Root";
import SignupPage from "./pages/Signup";
import WithdrawalPage from "./pages/Withdrawal";
const router = createBrowserRouter([
{
path: "/",
element: <RootLayout />,
children: [
{ index: true, element: <BungaeMainPage /> },
{ path: "/bungae/search", element: <BungaeSearchPage /> },
{ path: "/bungae/create", element: <CreateBungaePage /> },
{
path: "/bungae/:id",
children: [
{ index: true, element: <BungaeDetailPage /> },
{ path: "edit", element: <EditBungaePage /> }
]
},
{ path: "/signup", element: <SignupPage /> },
{
path: "/login",
element: <LoginPage />
},
{
path: "email-auth",
element: <EmailAuthPage />
},
{
path: "/profile/:nickname",
children: [
{ index: true, element: <ProfilePage /> },
{ path: "withdraw", element: <WithdrawalPage /> },
{ path: "modify", element: <ModifyUserInfoPage /> }
]
},
{ path: "*", element: <ErrorPage /> }
]
}
]);
function App() {
return <RouterProvider router={router} />;
}
export default App;
- createBrowserRouter : DOM History API를 사용하여 URL을 업데이트하고 기록 스택을 관리한다. loaders, actions 등과 같은 data API를 적용할 수 도 있다.
index
: true이면 부모의 url에서 부모의 Outlet으로 렌더링path
: url 경로 (/
가 앞에 붙으면 절대 경로, 없으면 상대 경로)element
: path 속성으로 지정한 경로에서 렌더링할 컴포넌트- RouterProvider : 작성한 라우터를 해당 컴포넌트에 전달하면 앱을 렌더링하고 loaders, actions 등과 같은 data API를 사용할 수 있다.
src/pages/Root.js
import { Outlet } from "react-router-dom";
import MainNavigation from "../components/MainNavigation";
function RootLayout() {
return (
<>
<MainNavigation />
<main>
<Outlet />
</main>
</>
);
}
export default RootLayout;
<RootLayout />
컴포넌트에서는 페이지마다 공통적으로 적용되는 상단 네비게이션 바를 가지는 레이아웃을 만들었다. 그리고 react-router
에서 제공하는 Outlet
컴포넌트를 사용해 url 경로마다 다르게 나타날 하위 경로의 페이지들을 렌더링하도록 처리했다. 그리고 모든 route를 하위로 감싸 해당 레이아웃을 한꺼번에 적용시켰다.
Outlet : 하위 경로 요소를 렌더링하기 위해 상위 경로 요소에서 사용해야 한다. 이렇게 하면 하위 경로가 렌더링될 때 중첩된 UI를 적용할 수 있다.