React Router v6์ ํ์ ๋ค๋น๊ฒ์ด์ ํจํด์ ํ์ํ์ธ์. ์ ์ธ์ ๋ผ์ฐํ , ๋์ ๋ผ์ฐํธ, ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์ ๋ค๋น๊ฒ์ด์ , ์ค์ฒฉ ๋ผ์ฐํธ, ๋ฐ์ดํฐ ๋ก๋ฉ ์ ๋ต์ ๋ฐฐ์ ๊ฒฌ๊ณ ํ๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
React Router v6: ์ต์ ์น ์ฑ์ ์ํ ๋ค๋น๊ฒ์ด์ ํจํด ๋ง์คํฐํ๊ธฐ
React Router v6๋ React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๋ผ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ ์ฒด ํ์ด์ง ์๋ก๊ณ ์นจ ์์ด ๋ค๋น๊ฒ์ด์ ์ ๊ด๋ฆฌํ์ฌ ๋๊น ์๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋จ์ผ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ (SPA)์ ๋ง๋ค ์ ์์ต๋๋ค. ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ์์๋ React Router v6๋ฅผ ์ฌ์ฉํ ํ์ ๋ค๋น๊ฒ์ด์ ํจํด์ ๊น์ด ํ๊ณ ๋ค์ด, ๊ฒฌ๊ณ ํ๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ํ์ํ ์ง์๊ณผ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.
React Router v6 ํต์ฌ ๊ฐ๋ ์ดํดํ๊ธฐ
ํน์ ํจํด์ ๋ํด ์์๋ณด๊ธฐ ์ ์ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ ๊ฐ๋ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
- ์ ์ธ์ ๋ผ์ฐํ : React Router๋ ์ ์ธ์ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉฐ, ๋ผ์ฐํธ๋ฅผ React ์ปดํฌ๋ํธ๋ก ์ ์ํฉ๋๋ค. ์ด๋ ๋ผ์ฐํ ๋ก์ง์ ๋ช ํํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ์ปดํฌ๋ํธ: ํต์ฌ ์ปดํฌ๋ํธ์๋
BrowserRouter,HashRouter,MemoryRouter,Routes,Route๊ฐ ํฌํจ๋ฉ๋๋ค. - ํ
(Hooks): React Router๋ ๋ผ์ฐํ
์ ๋ณด์ ์ ๊ทผํ๊ณ ๋ค๋น๊ฒ์ด์
์ ์กฐ์ํ๊ธฐ ์ํด
useNavigate,useLocation,useParams,useRoutes์ ๊ฐ์ ํ ์ ์ ๊ณตํฉ๋๋ค.
1. <Routes>์ <Route>๋ฅผ ์ด์ฉํ ์ ์ธ์ ๋ผ์ฐํ
React Router v6์ ๊ธฐ๋ฐ์ ์ ์ธ์ ๋ผ์ฐํ
์ ์์ต๋๋ค. <Routes>์ <Route> ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํธ๋ฅผ ์ ์ํฉ๋๋ค. <Routes> ์ปดํฌ๋ํธ๋ ๋ผ์ฐํธ๋ค์ ์ปจํ
์ด๋ ์ญํ ์ ํ๋ฉฐ, <Route> ์ปดํฌ๋ํธ๋ ํน์ ๋ผ์ฐํธ์ ํด๋น ๋ผ์ฐํธ๊ฐ ํ์ฌ URL๊ณผ ์ผ์นํ ๋ ๋ ๋๋งํ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํฉ๋๋ค.
์์ : ๊ธฐ๋ณธ ๋ผ์ฐํธ ์ค์
๋ค์์ ๊ฐ๋จํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ผ์ฐํธ๋ฅผ ์ค์ ํ๋ ๊ธฐ๋ณธ ์์ ์ ๋๋ค:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";
function App() {
return (
} />
} />
} />
);
}
export default App;
์ด ์์ ์์๋ ์ธ ๊ฐ์ง ๋ผ์ฐํธ๋ฅผ ์ ์ํฉ๋๋ค:
/:Home์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค./about:About์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค./contact:Contact์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
BrowserRouter ์ปดํฌ๋ํธ๋ ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ ๊ธฐ๋ฐ ๋ผ์ฐํ
์ ํ์ฑํํฉ๋๋ค. React Router๋ ํ์ฌ URL์ ์ ์๋ ๋ผ์ฐํธ์ ๋น๊ตํ์ฌ ํด๋นํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค.
2. URL ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ๋์ ๋ผ์ฐํธ
๋์ ๋ผ์ฐํธ๋ฅผ ์ฌ์ฉํ๋ฉด URL์ ๋ค๋ฅธ ๊ฐ๋ค์ ์ฒ๋ฆฌํ ์ ์๋ ๋ผ์ฐํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ์ ํ ID๋ ์ฌ์ฉ์ ID์ ๊ฐ์ ๊ณ ์ ์๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฝํ
์ธ ๋ฅผ ํ์ํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. React Router v6๋ : ๊ธฐํธ๋ฅผ ์ฌ์ฉํ์ฌ URL ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํฉ๋๋ค.
์์ : ์ ํ ์์ธ ์ ๋ณด ํ์
์ ์์๊ฑฐ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๊ณ ๊ฐ ์ ํ์ ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ธ ์ ๋ณด๋ฅผ ํ์ํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ๋ค์๊ณผ ๊ฐ์ด ๋์ ๋ผ์ฐํธ๋ฅผ ์ ์ํ ์ ์์ต๋๋ค:
import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";
function ProductDetails() {
const { productId } = useParams();
// productId๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ํ ์์ธ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
// ...
return (
Product Details
Product ID: {productId}
{/* ์ฌ๊ธฐ์ ์ ํ ์์ธ ์ ๋ณด ํ์ */}
);
}
function App() {
return (
} />
);
}
export default App;
์ด ์์ ์์๋:
/products/:productId๋:productId๊ฐ URL ํ๋ผ๋ฏธํฐ์ธ ๋์ ๋ผ์ฐํธ๋ฅผ ์ ์ํฉ๋๋ค.useParamsํ ์ProductDetails์ปดํฌ๋ํธ ๋ด์์productIdํ๋ผ๋ฏธํฐ์ ๊ฐ์ ์ ๊ทผํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.- ๊ทธ๋ฐ ๋ค์
productId๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์์ค์์ ํด๋นํ๋ ์ ํ ์์ธ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
๊ตญ์ ํ ์์ : ์ธ์ด ์ฝ๋ ์ฒ๋ฆฌ
๋ค๊ตญ์ด ์น์ฌ์ดํธ์ ๊ฒฝ์ฐ, ๋์ ๋ผ์ฐํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์ด ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค:
} />
์ด ๋ผ์ฐํธ๋ /en/about, /fr/about, /es/about์ ๊ฐ์ URL๊ณผ ์ผ์นํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ lang ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ํ ์ธ์ด ๋ฆฌ์์ค๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
3. useNavigate๋ฅผ ์ฌ์ฉํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์ ๋ค๋น๊ฒ์ด์
์ ์ธ์ ๋ผ์ฐํ
์ ์ ์ ๋งํฌ์ ํ๋ฅญํ์ง๋ง, ์ข
์ข
์ฌ์ฉ์ ์์
์ด๋ ์ ํ๋ฆฌ์ผ์ด์
๋ก์ง์ ๋ฐ๋ผ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ๋ค๋น๊ฒ์ด์
ํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค. React Router v6๋ ์ด๋ฅผ ์ํด useNavigate ํ
์ ์ ๊ณตํฉ๋๋ค. useNavigate๋ ๋ค๋ฅธ ๋ผ์ฐํธ๋ก ์ด๋ํ ์ ์๊ฒ ํด์ฃผ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค.
์์ : ํผ ์ ์ถ ํ ๋ฆฌ๋๋ ์
ํผ์ ์ ์ถํ๊ณ ์ฑ๊ณต์ ์ผ๋ก ์ ์ถ๋ ํ ์ฌ์ฉ์๋ฅผ ์ฑ๊ณต ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค:
import { useNavigate } from "react-router-dom";
function MyForm() {
const navigate = useNavigate();
const handleSubmit = async (event) => {
event.preventDefault();
// ํผ ๋ฐ์ดํฐ ์ ์ถ
// ...
// ์ฑ๊ณต์ ์ผ๋ก ์ ์ถ ํ ์ฑ๊ณต ํ์ด์ง๋ก ๋ฆฌ๋๋ ์
navigate("/success");
};
return (
);
}
export default MyForm;
์ด ์์ ์์๋:
useNavigateํ ์ ์ฌ์ฉํ์ฌnavigateํจ์๋ฅผ ๊ฐ์ ธ์ต๋๋ค.- ํผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ถ๋ ํ,
navigate("/success")๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉ์๋ฅผ/success๋ผ์ฐํธ๋ก ๋ฆฌ๋๋ ์ ํฉ๋๋ค.
๋ค๋น๊ฒ์ด์ ์ค ์ํ ์ ๋ฌ
navigate์ ๋ ๋ฒ์งธ ์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋น๊ฒ์ด์
๊ณผ ํจ๊ป ์ํ๋ฅผ ์ ๋ฌํ ์๋ ์์ต๋๋ค:
navigate("/confirmation", { state: { orderId: "12345" } });
์ด๋ฅผ ํตํด ๋์ ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์์ผ๋ฉฐ, ์ด ๋ฐ์ดํฐ๋ useLocation ํ
์ ์ฌ์ฉํ์ฌ ์ ๊ทผํ ์ ์์ต๋๋ค.
4. ์ค์ฒฉ ๋ผ์ฐํธ ๋ฐ ๋ ์ด์์
์ค์ฒฉ ๋ผ์ฐํธ๋ฅผ ์ฌ์ฉํ๋ฉด ํ ๋ผ์ฐํธ๊ฐ ๋ค๋ฅธ ๋ผ์ฐํธ ์์ ์ค์ฒฉ๋๋ ๊ณ์ธต์ ๋ผ์ฐํ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ์ฌ๋ฌ ์์ค์ ๋ค๋น๊ฒ์ด์ ์ด ์๋ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ์ด๋ ํน์ UI ์์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์น์ ์ ์ฒด์ ๊ฑธ์ณ ์ผ๊ด๋๊ฒ ํ์๋๋ ๋ ์ด์์์ ๋ง๋๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์์ : ์ฌ์ฉ์ ํ๋กํ ์น์
์ฌ์ฉ์์ ํ๋กํ ์ ๋ณด, ์ค์ ๋ฐ ์ฃผ๋ฌธ์ ํ์ํ๊ธฐ ์ํ ์ค์ฒฉ ๋ผ์ฐํธ๊ฐ ์๋ ์ฌ์ฉ์ ํ๋กํ ์น์ ์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค:
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function Profile() {
return (
์ฌ์ฉ์ ํ๋กํ
-
ํ๋กํ ์ ๋ณด
-
์ค์
-
์ฃผ๋ฌธ
} />
} />
} />
);
}
function ProfileInformation() {
return ํ๋กํ ์ ๋ณด ์ปดํฌ๋ํธ
;
}
function Settings() {
return ์ค์ ์ปดํฌ๋ํธ
;
}
function Orders() {
return ์ฃผ๋ฌธ ์ปดํฌ๋ํธ
;
}
function App() {
return (
} />
);
}
export default App;
์ด ์์ ์์๋:
/profile/*๋ผ์ฐํธ๋/profile๋ก ์์ํ๋ ๋ชจ๋ URL๊ณผ ์ผ์นํฉ๋๋ค.Profile์ปดํฌ๋ํธ๋ ๋ค๋น๊ฒ์ด์ ๋ฉ๋ด์ ์ค์ฒฉ ๋ผ์ฐํธ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ<Routes>์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํฉ๋๋ค.- ์ค์ฒฉ ๋ผ์ฐํธ๋
/profile/info,/profile/settings,/profile/orders์ ๋ํด ๋ ๋๋งํ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํฉ๋๋ค.
๋ถ๋ชจ ๋ผ์ฐํธ์ *๋ ๋ถ๋ชจ ๋ผ์ฐํธ๊ฐ ๋ชจ๋ ํ์ ๊ฒฝ๋ก์ ์ผ์นํด์ผ ํจ์ ์๋ฏธํ๋ฉฐ, ์ด๋ฅผ ํตํด ์ค์ฒฉ ๋ผ์ฐํธ๊ฐ Profile ์ปดํฌ๋ํธ ๋ด์์ ์ฌ๋ฐ๋ฅด๊ฒ ์ผ์น๋๋๋ก ํฉ๋๋ค.
5. "์ฐพ์ ์ ์์" (404) ์ค๋ฅ ์ฒ๋ฆฌ
์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์๋ ๋ผ์ฐํธ๋ก ์ด๋ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. React Router v6๋ catch-all ๋ผ์ฐํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
์์ : 404 ํ์ด์ง ๊ตฌํ
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function NotFound() {
return (
404 - ํ์ด์ง๋ฅผ ์ฐพ์ ์ ์์
์ฐพ์ผ์๋ ํ์ด์ง๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.
ํ์ผ๋ก ๋์๊ฐ๊ธฐ
);
}
function App() {
return (
} />
} />
} />
);
}
์ด ์์ ์์๋:
<Route path="*" element={<NotFound />} />๋ผ์ฐํธ๋ ๋ค๋ฅธ ์ ์๋ ๋ผ์ฐํธ์ ์ผ์นํ์ง ์๋ ๋ชจ๋ URL๊ณผ ์ผ์นํ๋ catch-all ๋ผ์ฐํธ์ ๋๋ค.- ์ด ๋ผ์ฐํธ๋ ๋ค๋ฅธ ๋ผ์ฐํธ๊ฐ ์ผ์นํ์ง ์์ ๊ฒฝ์ฐ์๋ง ์ผ์นํ๋๋ก
<Routes>์ปดํฌ๋ํธ์ ๋์ ๋ฐฐ์นํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
6. React Router v6์ ๋ฐ์ดํฐ ๋ก๋ฉ ์ ๋ต
React Router v6๋ ์ด์ ๋ฒ์ (useRouteMatch๊ฐ ์๋ React Router v5)๊ณผ ๋ฌ๋ฆฌ ๋ด์ฅ๋ ๋ฐ์ดํฐ ๋ก๋ฉ ๋ฉ์ปค๋์ฆ์ ํฌํจํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ค์ํ ๋ฐ์ดํฐ ๋ก๋ฉ ์ ๋ต์ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ ์ ์๋ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ต์ 1: ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
๊ฐ์ฅ ๊ฐ๋จํ ์ ๊ทผ ๋ฐฉ์์ ๋ผ์ฐํธ๋ฅผ ๋ ๋๋งํ๋ ์ปดํฌ๋ํธ ๋ด์์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์
๋๋ค. useEffect ํ
์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋๊ฑฐ๋ URL ํ๋ผ๋ฏธํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
function ProductDetails() {
const { productId } = useParams();
const [product, setProduct] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchProduct() {
try {
const response = await fetch(`/api/products/${productId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setProduct(data);
setLoading(false);
} catch (e) {
setError(e);
setLoading(false);
}
}
fetchProduct();
}, [productId]);
if (loading) return ๋ก๋ฉ ์ค...
;
if (error) return ์ค๋ฅ: {error.message}
;
if (!product) return ์ ํ์ ์ฐพ์ ์ ์์ต๋๋ค
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
์ด ์ ๊ทผ ๋ฐฉ์์ ๊ฐ๋จํ์ง๋ง ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ ๊ฒฝ์ฐ ์ฝ๋ ์ค๋ณต์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๊ฐ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ํ์๋ง ์์๋๋ฏ๋ก ๋ ํจ์จ์ ์ ๋๋ค.
์ต์ 2: ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํ ์ปค์คํ ํ ์ฌ์ฉ
์ฝ๋ ์ค๋ณต์ ์ค์ด๊ธฐ ์ํด ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ก์ง์ ์บก์ํํ๋ ์ปค์คํ ํ ์ ๋ง๋ค ์ ์์ต๋๋ค. ์ด ํ ์ ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
import { useState, useEffect } from "react";
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
setData(json);
setLoading(false);
} catch (e) {
setError(e);
setLoading(false);
}
}
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
๊ทธ๋ฐ ๋ค์ ์ปดํฌ๋ํธ์์ ์ด ํ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import { useParams } from "react-router-dom";
import useFetch from "./useFetch";
function ProductDetails() {
const { productId } = useParams();
const { data: product, loading, error } = useFetch(`/api/products/${productId}`);
if (loading) return ๋ก๋ฉ ์ค...
;
if (error) return ์ค๋ฅ: {error.message}
;
if (!product) return ์ ํ์ ์ฐพ์ ์ ์์ต๋๋ค
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
์ต์ 3: ๋ฐ์ดํฐ ๋ก๋ฉ ๊ธฐ๋ฅ์ด ์๋ ๋ผ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ (TanStack Router, Remix)
TanStack Router ๋ฐ Remix์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ผ์ฐํ ๊ณผ ์ํํ๊ฒ ํตํฉ๋๋ ๋ด์ฅ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ข ์ข ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:
- ๋ก๋(Loaders): ๋ผ์ฐํธ๊ฐ ๋ ๋๋ง๋๊ธฐ *์ ์* ์คํ๋๋ ํจ์๋ก, ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์ปดํฌ๋ํธ์ ์ ๋ฌํ ์ ์์ต๋๋ค.
- ์ก์ (Actions): ํผ ์ ์ถ ๋ฐ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ฒ๋ฆฌํ๋ ํจ์์ ๋๋ค.
์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ํนํ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ๋ก๋ฉ์ ๋ํญ ๋จ์ํํ๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR) ๋ฐ ์ ์ ์ฌ์ดํธ ์์ฑ(SSG)
ํฅ์๋ SEO ๋ฐ ์ด๊ธฐ ๋ก๋ฉ ์ฑ๋ฅ์ ์ํด Next.js๋ Gatsby์ ๊ฐ์ ํ๋ ์์ํฌ์ ํจ๊ป SSR ๋๋ SSG๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํด ๋ณด์ธ์. ์ด๋ฌํ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ฒ์์ ๋๋ ๋น๋ ํ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์ฌ์ ๋ ๋๋ง๋ HTML์ ํด๋ผ์ด์ธํธ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด๋ ํด๋ผ์ด์ธํธ๊ฐ ์ด๊ธฐ ๋ก๋ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ํ์๊ฐ ์๊ฒ ํ์ฌ ๋ ๋น ๋ฅด๊ณ SEO ์นํ์ ์ธ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
7. ๋ค์ํ ๋ผ์ฐํฐ ์ ํ ์์ ํ๊ธฐ
React Router v6๋ ๋ค์ํ ํ๊ฒฝ๊ณผ ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋ ์ฌ๋ฌ ๋ผ์ฐํฐ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค:
- BrowserRouter: ๋ค๋น๊ฒ์ด์
์ ์ํด HTML5 ํ์คํ ๋ฆฌ API(
pushState,replaceState)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ ์คํ๋๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ ํ์ ๋๋ค. - HashRouter: ๋ค๋น๊ฒ์ด์
์ ์ํด URL์ ํด์ ๋ถ๋ถ(
#)์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๊ตฌํ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ง์ํด์ผ ํ๊ฑฐ๋ HTML5 ํ์คํ ๋ฆฌ API๋ฅผ ์ง์ํ์ง ์๋ ์๋ฒ์ ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํฉ๋๋ค. - MemoryRouter: "URL"์ ํ์คํ ๋ฆฌ๋ฅผ ๋ฉ๋ชจ๋ฆฌ(URL ๋ฐฐ์ด)์ ์ ์งํฉ๋๋ค. React Native ๋ฐ ํ ์คํธ์ ๊ฐ์ ํ๊ฒฝ์์ ์ ์ฉํฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ตฌ ์ฌํญ๊ณผ ํ๊ฒฝ์ ๊ฐ์ฅ ์ ํฉํ ๋ผ์ฐํฐ ์ ํ์ ์ ํํ์ธ์.
๊ฒฐ๋ก
React Router v6๋ React ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ ํฌ๊ด์ ์ด๊ณ ์ ์ฐํ ๋ผ์ฐํ
์๋ฃจ์
์ ์ ๊ณตํฉ๋๋ค. ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ์์ ๋
ผ์๋ ๋ค๋น๊ฒ์ด์
ํจํด์ ์ดํดํ๊ณ ์ ์ฉํจ์ผ๋ก์จ ๊ฒฌ๊ณ ํ๊ณ ์ฌ์ฉ์ ์นํ์ ์ด๋ฉฐ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ ์ ์์ต๋๋ค. <Routes>์ <Route>๋ฅผ ์ด์ฉํ ์ ์ธ์ ๋ผ์ฐํ
๋ถํฐ URL ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ๋์ ๋ผ์ฐํธ, useNavigate๋ฅผ ์ฌ์ฉํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์ ๋ค๋น๊ฒ์ด์
, ํจ๊ณผ์ ์ธ ๋ฐ์ดํฐ ๋ก๋ฉ ์ ๋ต์ ์ด๋ฅด๊ธฐ๊น์ง, React Router v6๋ ์ฌ์ฉ์์๊ฒ ์ํํ ๋ค๋น๊ฒ์ด์
๊ฒฝํ์ ์ ๊ณตํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ๋ ํฐ ์ ์ด์ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ๊ณ ๊ธ ๋ผ์ฐํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ SSR/SSG ํ๋ ์์ํฌ๋ฅผ ํ์ํ๋ ๊ฒ์ ๊ณ ๋ คํด ๋ณด์ธ์. ํน์ ์ ํ๋ฆฌ์ผ์ด์
์๊ตฌ ์ฌํญ์ ๋ง๊ฒ ์ด๋ฌํ ํจํด์ ์กฐ์ ํ๊ณ ํญ์ ๋ช
ํํ๊ณ ์ง๊ด์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ์ฐ์ ์ํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.