SPA๋ "Single Page Application"์ ์ฝ์๋ก, ์น ์๋น์ค์ ์ค์ํ ์ํคํ ์ฒ ํจํด ์ค ํ๋์ ๋๋ค.
SPA๋ "Single Page Application"์ ์ฝ์๋ก, ์น ์๋น์ค์ ์ค์ํ ์ํคํ ์ฒ ํจํด ์ค ํ๋์ ๋๋ค. SPA๋ ๋จ์ผ HTML ํ์ผ์ ๋ก๋ํ ํ, ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ๋ค์ํ ํ๋ฉด ๋๋ ๋ทฐ๋ก ์ด๋ํ ๋ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํ์ง ์๊ณ ๋ ์ปจํ ์ธ ๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค. ์ด๋ฌํ SPA์ ํน์ง์ ์น ์๋น์ค๋ฅผ ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ฉฐ UX๋ฅผ ํฅ์์ํต๋๋ค.
Client Side Routing์ SPA์ ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋ ๊ฐ๋ ์ ๋๋ค. SPA์์๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์ด๊ธฐ์ ํ ๋ฒ๋ง HTML, CSS, ๋ฐ JavaScript ํ์ผ์ ๋ก๋ํ๊ณ ์ดํ์๋ ์๋ฒ์ ํ์ด์ง๋ฅผ ์์ฒญํ์ง ์๊ณ ํด๋ผ์ด์ธํธ ์ธก์์ ํ์ด์ง ๊ฐ์ ์ ํ์ ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ Client Side Routing์ด ์ฌ์ฉ๋ฉ๋๋ค.
์๋๋ spa์ ํน์ง์ค ํ๋์ธ Client Side Routing์ ๋ํ ์ค๋ช ์ ๋๋ค.
Client Side Routing์ ์ฌ์ฉ์๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ ๋ ์๋ฒ์ ์๋ก์ด ํ์ด์ง๋ฅผ ์์ฒญํ์ง ์๊ณ ๋ ํ์ด์ง๋ฅผ ๋น ๋ฅด๊ฒ ๋ก๋ํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์๋ฒ์์ ํต์ ๋ถ๋ด์ ์ค์ด๊ณ ์ฌ์ฉ์์๊ฒ ๋น ๋ฅธ ์๋ต ์๊ฐ์ ์ ๊ณตํฉ๋๋ค.
์ ํต์ ์ธ ์น ์ฌ์ดํธ์์๋ ์ฌ์ฉ์๊ฐ ์๋ก๊ณ ์นจ ๋ฒํผ์ ๋๋ฅด๊ฑฐ๋ ์๋ก์ด ๋งํฌ๋ฅผ ํด๋ฆญํ ๋๋ง๋ค ํ์ด์ง๊ฐ ๋ค์ ๋ก๋๋๋ฉฐ ์ ์ฒด ํ๋ฉด์ด ๊ฐฑ์ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ ์ฌ์ฉํ๋ฉด ํ์ด์ง ์ด๋ ์์ ์๋ก๊ณ ์นจ์ด ๋ฐ์ํ์ง ์๊ณ ํ์ด์ง์ ์ผ๋ถ๋ง ์ ๋ฐ์ดํธ๋ฉ๋๋ค. ์ด๋ก์จ ๋ถ๋๋ฌ์ด UX์ ์ ๊ณตํ๋ฉฐ ํ๋ฉด ๊น๋นก์์ด๋ ์๋ต ์ง์ฐ์ ์ต์ํํฉ๋๋ค.
Client Side Routing์ ํตํด ํ์ด์ง ์ ํ ์์ UI๋ฅผ ๋์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ ๋ ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์ ธ์์ ํ์ด์ง ๋ด์ฉ์ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์ด๋ก์จ ์ฌ์ฉ์์๊ฒ ๋ณด๋ค ์ธํฐ๋ํฐ๋ธํ๊ณ ๋์ ์ธ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ URL์ ์ฌ์ฉํ์ฌ ํ์ฌ ํ์ด์ง ์ํ๋ฅผ ํ์ํ๊ณ ๊ด๋ฆฌํฉ๋๋ค. ์ด๊ฒ์ ๋ธ๋ผ์ฐ์ ์ ๋ค๋ก ๊ฐ๊ธฐ ๋ฐ ์์ผ๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ์ง์ํ๊ณ , ๋ถ๋งํฌ๋ฅผ ์์ฑํ๊ฑฐ๋ ํน์ ์ํ๋ก ๊ณต์ ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
SPA์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ ๋ชจ๋ ํ๋์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์์ ์ค์ํ ์์๋ก, ์ฌ์ฉ์์๊ฒ ๋น ๋ฅด๊ณ ๋ถ๋๋ฌ์ด UX๋ฅผ ์ ๊ณตํ๋ ๋ฐ ํฌ๊ฒ ๊ธฐ์ฌํฉ๋๋ค. React Router๋ SPA์ Client Side Routing์ ๊ตฌํํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
createBrowserRouter๋ React Router v6์์ ์๋กญ๊ฒ ๋์ ๋ API ์ค ํ๋๋ก, ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํจ์๋ ๋ผ์ฐํฐ ๊ตฌ์ฑ์ ๊ฐ์ฒด ํํ๋ก ์ ์ธ์ ์ผ๋ก ๋ง๋ค ์ ์๊ฒ ํด์ฃผ๋ฉฐ, ์ด๋ฅผ BrowserRouter ์ปดํฌ๋ํธ์ ์ ๋ฌํ์ฌ ๋ผ์ฐํ ์ ์ค์ ํฉ๋๋ค. createBrowserRouter๋ฅผ ์ฌ์ฉํ๋ฉด route์ ๋ํ ์์ธํ ์ ์์ route์ ๋ํ ์ฌ๋ฌ ๊ฐ์ง ์ถ๊ฐ ์ค์ ์ ํ ์ ์์ต๋๋ค. ์ง๊ธ๊น์ง ์ฌ์ฉํด์ค๋ Router ์ปดํฌ๋ํธ์ ๋น๊ตํด์ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
// React Router v6์์์ Route ์ฌ์ฉ ์
import { Route, Routes } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="about" element={<AboutPage />} />
{/* ์ถ๊ฐ Route ์ ์ */}
</Routes>
);
}
// React Router v6์์์ createBrowserRouter ์ฌ์ฉ ์
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <HomePage />,
// ์ฌ๊ธฐ์ ํ์ ๋ผ์ฐํธ๋ ๋ก๋(loader), ์ก์
(action) ๋ฑ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
},
{
path: "about",
element: <AboutPage />,
},
// ์ถ๊ฐ ๋ผ์ฐํธ ์ ์
]);
function App() {
return <RouterProvider router={router} />;
}
๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ ์ฐจ์ด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. Route ์ปดํฌ๋ํธ์์๋ ๋น์ทํ ๊ธฐ๋ฅ์ ์ํํ ์ ์์ง๋ง, createBrowserRouter๋ฅผ ์ด์ฉํ๋ค๋ฉด ์์ธํ ์ฝ๋ ์์ฑ์ด ๊ฐ๋ฅํฉ๋๋ค.
{
path: "/",
element: <Root />,
loader: rootLoader,
children: [
{
path: "team",
element: <Team />,
loader: teamLoader,
},
],
},
์ด๋ ํด๋น ์ฝ๋์ ๋ํ children์ ์ฌ์ฉํ๋ฉฐ, Rootํ์ด์ง ๋ด๋ถ ํ์ path๊ฐ team์ ๊ฒฝ์ฐ Team ์ด๋ผ๋ ํ์ด์ง ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด rendering์ด ๊ฐ๋ฅํฉ๋๋ค ์์ ์ฝ๋์์ ์ฃผ์ ํด์ผํ๋ ๋ถ๋ถ์ loader์ ๋๋ค.
๊ฐ ๊ฒฝ๋ก๋ ๋ ๋๋ง๋๊ธฐ ์ ์ ๊ฒฝ๋ก ์์์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ "๋ก๋" ๊ธฐ๋ฅ์ ์ ์ํ ์ ์์ต๋๋ค.
createBrowserRouter([
{
path: "/teams/:teamId",
loader: ({ params }) => {
return fakeGetTeam(params.teamId);
},
},
]);
// ๋ค์๊ณผ ๊ฐ์ด ๊ฐ ํ์ด์ง๋ฅผ loadํ๊ธฐ ์ ๋ถํฐ loader๋ฅผ ํตํด์ ์๋ฌ, ํน์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌํ(NDD)์ ์๋น์ค์ธ ๊ณฐํฐ๋ทฐ๋ ์๋น์ค ํน์ฑ์ ๋ฉด์ ์ ๋ค์ด๊ฐ๊ธฐ ์ ์ ์ฌ๋ฌ setting์ ํด์ผํ๋ ๊ณผ์ ์ ๊ฒธํ๊ณ ์์ต๋๋ค.(๋ฌธ์ ๋ฅผ ์ ์ , ์นด๋ฉ๋ผ ๋ฐ ๋ง์ดํฌ ์ฐ๊ฒฐ, ์ ์ฅ์ ์ ํ ๋ฑ) ๋ฐ๋ผ์ ํ์ด์ง๋ณ route๋ฅผ ์ด๋ํ ๋ ์ฌ๋ฌ error์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ผํ๋๋ฐ, ์ด๋ ํด๋น ํ์ผ์์ ๋ช ํํ ์ฑ ์ ๋ถ๋ฆฌ๊ฐ ๊ฐ๋ฅํ ๊ฒ์ด๋ผ ์๊ฐํ์ต๋๋ค.
๊ฐ ํ์ด์ง ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ์ดํ๊ฐ ์๋, ์ ์ด์ router์ฒ๋ฆฌ๋ฅผ ํ๋ฉด์ ๋ง์์ค๋ค๋ฉด ์ข ๋ ๋ช ํํ ์ฑ ์์ ๊ฐ์ง๋ค๋ ์๊ฐ์ด์์ต๋๋ค. ์ด๋ฟ์ด ์๋๋ผ lazy-loading์ ํตํ ์ฝ๋ ์คํ๋ฆฌํ ์๋ ๊ทนํ ์ ๋ฆฌ ํฉ๋๋ค.
lazy-loader๋ฅผ ํตํด์ ์ดํ๋ฆฌ์ผ์ด์ ๋ธ๋ค์ ์๊ฒ ์ ์งํ๋ฉด์ ํด๋น ๊ฒฝ๋ก์ ์ฝ๋ ๋ถํ์ ์ง์ํ ์ ์๋ ์ฌ๋ฌ๊ฐ์ง ๋น๋๊ธฐ ๊ธฐ๋ฅ์ ํ๊ธฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์๋ค๋ ์ ์ด ๋งค๋ ฅ์ ์ด์์ต๋๋ค.
์๋๋ createBrowserRouter์ ์ข ํฉ์ ์ธ ๊ธฐ๋ฅ๊ณผ ์์์ ๋๋ค.
์ ์ธ์ ๋ผ์ฐํธ ๊ตฌ์ฑ: createBrowserRouter๋ฅผ ์ฌ์ฉํ๋ฉด JavaScript ๊ฐ์ฒด๋ก ๋ผ์ฐํธ๋ฅผ ์ ์ธ์ ์ผ๋ก ์ ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ผ์ฐํธ์ ๊ตฌ์กฐ์ ๊ด๋ จ ์ปดํฌ๋ํธ๋ฅผ ๋ณด๋ค ๋ช ํํ๊ฒ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ๋ก๋ฉ ๋ฐ ์ฝ๋ ๋ถํ ์ง์: ๋ผ์ฐํธ ๊ฐ์ฒด ๋ด์์ loader ํจ์๋ฅผ ์ ์ํ ์ ์์ด์, ํด๋น ๋ผ์ฐํธ๊ฐ ํ์ฑํ๋ ๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ฉํ ์ ์์ต๋๋ค. ๋ํ, import()๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ก๋ํ๋ ์ฝ๋ ๋ถํ ๋ ์ง์ํฉ๋๋ค.
๋ด์ฅ๋ ์๋ฌ ํธ๋ค๋ง: createBrowserRouter๋ฅผ ์ฌ์ฉํ๋ฉด ๋ผ์ฐํธ ๊ฐ์ฒด์ errorElement๋ฅผ ์ ๊ณตํ์ฌ ํน์ ๊ฒฝ๋ก์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ์ฌ์ฉ์์๊ฒ ํ์ํ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.
ํฅ์๋ ์ฑ๋ฅ: ์๋ก์ด ๋ผ์ฐํฐ๋ ๋ผ์ฐํธ ๋งค์นญ๊ณผ ๋ ๋๋ง ์ต์ ํ๋ฅผ ์ํด ๋ด๋ถ์ ์ผ๋ก ํฅ์๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ์ด ๊ฐ์ ๋์์ต๋๋ค.
ํ์คํ ๋ฆฌ API์์ ํตํฉ: createBrowserRouter๋ HTML5 ํ์คํ ๋ฆฌ API์ ๊ธด๋ฐํ๊ฒ ํตํฉ๋์ด ์์ด, ๋ธ๋ผ์ฐ์ ์ ๋ค๋ก ๊ฐ๊ธฐ/์์ผ๋ก ๊ฐ๊ธฐ ๊ธฐ๋ฅ๊ณผ ์๋ฒฝํ๊ฒ ํธํ๋ฉ๋๋ค.
๊ฒฝ๋ก ๋ณดํธ ๊ธฐ๋ฅ: createBrowserRouter๋ฅผ ์ฌ์ฉํ ๋, loader ํจ์ ๋ด์์ ์ฌ์ฉ์ ์ธ์ฆ ์ํ๋ฅผ ํ์ธํ๊ณ , ํ์ํ ๊ฒฝ์ฐ ๋ค๋ฅธ ๊ฒฝ๋ก๋ก ๋ฆฌ๋ค์ด๋ ํธํ๋ ๋ฑ์ ๋ณด์ ๊ฒฝ๋ก๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
์ค์ฒฉ๋ ๋ผ์ฐํธ: ์ค์ฒฉ๋ ๋ผ์ฐํธ๋ฅผ ํตํด ๋ ์ด์์ ๋ด์ ํ์ ๊ฒฝ๋ก๋ค์ ์ ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ณต์กํ UI ๊ตฌ์กฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import React, { lazy, Suspense } from "react";
import Layout from "./components/Layout";
import ErrorPage from "./components/ErrorPage";
import Loading from "./components/Loading";
import { fetchUserData } from "./utils/auth";
// ์ฌ์ฉํ ์ปดํฌ๋ํธ๋ฅผ lazy๋ก ๋ถ๋ฌ์ด์ผ๋ก์จ ์ฝ๋ ๋ถํ ๊ตฌํ
const HomePage = lazy(() => import("./pages/HomePage"));
const ProfilePage = lazy(() => import("./pages/ProfilePage"));
const LoginPage = lazy(() => import("./pages/LoginPage"));
const router = createBrowserRouter([
{
path: "/",
element: <Layout />, // ๊ธฐ๋ณธ ๋ ์ด์์
errorElement: <ErrorPage />, // ์๋ฌ ๋ฐ์ ์ ํ์๋ ์ปดํฌ๋ํธ
children: [
{
index: true,
element: (
<Suspense fallback={<Loading />}>
<HomePage />
</Suspense>
),
},
{
path: "profile",
element: (
<Suspense fallback={<Loading />}>
<ProfilePage />
</Suspense>
),
loader: async () => {
// ์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ฉ
const userData = await fetchUserData();
if (!userData) {
throw new Error("User not found");
}
return userData;
},
},
{
path: "login",
element: (
<Suspense fallback={<Loading />}>
<LoginPage />
</Suspense>
),
},
],
},
// ๊ฒฝ๋ก ๋ณดํธ๋ฅผ ์ํ ์์
{
path: "protected",
element: (
<Suspense fallback={<Loading />}>
<ProtectedPage />
</Suspense>
),
loader: async () => {
const user = await fetchUserData();
if (!user) {
// ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ์ง ์์๋ค๋ฉด ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ
throw new Response(null, { status: 403 });
}
},
},
]);
function App() {
return <RouterProvider router={router} />;
}
export default App;
์ด์ : react-router-dom์ Link ํ๊ทธ๋ก๋ ์ ์ด๋ํ์ง๋ง ์ด๋ํ ์์น์์ ์๋ก ๊ณ ์นจ์ํ๋ฉด ์ด๋์ด ๋ถ๊ฐํ ๋ฌธ์ ๊ฐ ๋ฐ์
์ด ๋ฌธ์ ๋ Single Page Applications (SPA)์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
๊ณผ ์๋ฒ ์ธก ๋ผ์ฐํ
๋ฐฉ์์ ์ฐจ์ด์์ ๋ฐ์ํ์ต๋๋ค. react-router-dom
๊ฐ์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ธ๋ผ์ฐ์ ์ ์ฃผ์ ํ์์ค์ URL์ ๋ณ๊ฒฝํ์ง๋ง, ์ค์ ๋ก ์๋ฒ์ ์๋ก์ด ์์ฒญ์ ๋ณด๋ด์ง ์์ต๋๋ค. ๋์ , JavaScript๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ธก์์ ๋์ ์ผ๋ก ์ฝํ
์ธ ๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
์ด์ ๋์กฐ์ ์ผ๋ก, ์๋ฒ ์ธก ๋ผ์ฐํ ์ URL์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์๋ฒ๋ก ์ ์์ฒญ์ ๋ณด๋ด ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํฉ๋๋ค. SPA์์๋ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ ์ฌ์ฉํ๋ฏ๋ก, ์๋ฒ๋ ์ด๋ค ํน์ ๊ฒฝ๋ก์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ชฐ๋ผ์ 404 Not Found ์๋ฌ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, http://example.com/user
ํ์ด์ง๋ฅผ ๋ณด๊ณ ์๋ค๊ฐ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ์๋ฒ์ /user
๊ฒฝ๋ก์ ๋ํ ์ ํ์ด์ง๋ฅผ ์์ฒญํฉ๋๋ค. SPA๋ฅผ ํธ์คํ
ํ๋ ์๋ฒ๊ฐ ์ด ๊ฒฝ๋ก์ ๋ํด ์ค์ ๋์ง ์์๋ค๋ฉด, ์๋ฒ๋ 404 ์๋ฌ๋ฅผ ๋ฐํํ ๊ฒ์
๋๋ค. ๊ทธ ์ด์ ๋, ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํฐ๋ง์ด /user
๊ฒฝ๋ก๊ฐ ์ ํจํ๋ค๋ ๊ฒ์ ์๊ณ ์๊ณ , ์๋ฒ๋ ์๋๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด historyApiFallback
์ค์ ์ด ์ฌ์ฉ๋ฉ๋๋ค. ์ด ์ค์ ์ ํ์ฑํํ๋ฉด, Webpack Dev Server๋ ๊ฐ๋ฐ ์ค์ ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํธ์ ๋ํ 404 ์๋ต์ **index.html
**๋ก ๋ฆฌ๋ค์ด๋ ์
ํฉ๋๋ค. ์ด๋ **index.html
**์ด ์ค์ ๋ก๋ SPA์ ์ง์
์ ์ด๋ฉฐ, ํด๋ผ์ด์ธํธ ์ธก JavaScript๊ฐ ํ์ํ ๋ผ์ฐํ
์ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ฐ๋ผ์, ์ฌ์ฉ์๊ฐ ์๋ก๊ณ ์นจ์ ํ๊ฑฐ๋ ์ง์ URL์ ์
๋ ฅํ์ฌ ํน์ ๊ฒฝ๋ก๋ก ์ ๊ทผํ ๋, historyApiFallback
์ค์ ์ด ์๋ ์๋ฒ๋ ์์ฒญ์ **index.html
**๋ก ๋ฆฌ๋ค์ด๋ ํธํ๊ณ , ๊ทธ ํ์ **react-router-dom
**์ด URL์ ํ์ธํ์ฌ ์ ์ ํ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค. ์ด๋ก ์ธํด ํด๋ผ์ด์ธํธ ์ธก์์ ์ ์ํ ๋ผ์ฐํธ๊ฐ ์๋ฒ ์ธก์์๋ ๋ฌธ์ ์์ด ์๋ํ๊ฒ ๋ฉ๋๋ค.
๋ค์ ์ฝ๋์ ๊ฐ์ด webpack ์ค์ ์ ์ถ๊ฐํด์ค์ผ๋ก์ ํด๊ฒฐํ์ต๋๋ค.
์ง๊ธ๊น์ง ํ๋ก์ ํธ์ ์ค์ํ ๋ถ๋ถ์ธ createBrowserRouter๋ฅผ ํตํ Router์ฒ๋ฆฌ์ ๋ํ ๋ผ๋๋ฅผ ์ก์์ต๋๋ค. ์์ง์ ๋ฐ์๋์ง ์์์ผ๋, setting ํ์ด์ง๋ฅผ ์ค๊ฐ๋ฉฐ ๋ฐ์ํ ์ฌ๋ฌ ํ์ด์ง์์์ ๋ฌธ์ ๋ฅผ createBrowserRouter์์ ํด๊ฒฐํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
ํด๋น ๊ฐ๋ฐ ๋ด์ฉ์ ๋ํ ๋ด์ฉ์ PR์์ ํ์ธํ ์ ์์ต๋๋ค.