
📅 2025-10-21
➡️ React Router DOM에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리
// src/Router.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
import Contact from "../pages/Contact";
import Works from "../pages/Works";
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
<Route path="works" element={<Works />} />
{/* 동적 라우트 추가 */}
<Route path="works/:id" element={<Works />} />
</Routes>
</BrowserRouter>
);
};
export default Router;
/works/1, /works/2, /works/3 … 처럼 각 work가 개별 페이지를 가질 때, 모든 경로를 하나하나 지정하는 대신 동적 경로(:id)로 한 번에 처리할 수 있음:id → URL의 가변적인 부분을 의미하는 파라미터 변수:id 값은 useParams() 훅을 사용해 조회 가능import React from 'react';
import { useParams } from 'react-router-dom';
const data = [
{ id: 1, todo: '리액트 배우기' },
{ id: 2, todo: 'supabase 배우기' },
{ id: 3, todo: '자바스크립트 배우기' },
{ id: 4, todo: 'DB 배우기' },
{ id: 5, todo: '넥스트 배우기' },
{ id: 6, todo: 'HTTP 프로토콜 배우기' },
];
function Work() {
const param = useParams();
const work = data.find((work) => work.id === parseInt(param.id));
return <div>{work.todo}</div>;
}
export default Work;useSearchParams는 현재 URL의 쿼리스트링(query string)을 읽고 수정할 수 있는 훅?key=value 형태 데이터를 상태처럼 관리할 수 있게 해줌import { useSearchParams } from "react-router-dom";
function Works() {
const [searchParams, setSearchParams] = useSearchParams();
const keyword = searchParams.get("keyword"); // 쿼리값 읽기
const handleChange = (e) => {
// 입력할 때마다 URL 쿼리 갱신
setSearchParams({ keyword: e.target.value });
};
return (
<div>
<input value={keyword || ""} onChange={handleChange} />
<p>검색어: {keyword}</p>
</div>
);
}keyword=리액트 → /works?keyword=리액트 형태로 주소창에 표시| 메서드 | 설명 |
|---|---|
searchParams.get(key) | 특정 key의 첫 번째 value 반환 |
searchParams.getAll(key) | 특정 key의 모든 value를 배열로 반환 |
searchParams.set(key, value) | 인자로 전달한 key 값을 value로 설정 (기존 값 덮어씀) |
searchParams.append(key, value) | 기존 값을 유지하고 새 값을 추가 |
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import DashboardLayout from './DashboardLayout';
import Profile from './Profile';
import Settings from './Settings';
import Reports from './Reports';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<Profile />} />
<Route path="settings" element={<Settings />} />
<Route path="reports" element={<Reports />} />
</Route>
</Routes>
</BrowserRouter>
);
}/dashboard → DashboardLayout 렌더링/dashboard/settings, /dashboard/reports → 같은 레이아웃을 공유하면서 내부 내용만 변경Outlet은 부모 라우트 내에서 자식 라우트가 렌더링될 위치를 지정import { Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<header>Header Section</header>
<main>
{/* 자식 라우트가 렌더링되는 위치 */}
<Outlet />
</main>
<footer>Footer Section</footer>
</div>
);
}| 구분 | 중첩 라우팅 | 공통 레이아웃 |
|---|---|---|
| 구조 | <Route> 내부에 <Route> 정의 | 라우트 외부에서 <Layout>으로 감싸기 |
| 렌더링 위치 | <Outlet />에 하위 라우트 렌더링 | <Layout> 내의 <Routes>에 페이지 표시 |
| 장점 | 계층적이고 동적 관리에 유리 | 단순하고 일관된 구조 유지에 유리 |
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</Layout>
import { Navigate } from "react-router-dom";
// 문지기 역할 컴포넌트
function ProtectedRoute({ isAllowed, children }) {
if (!isAllowed) {
// 조건을 만족하지 않으면 Home으로 돌려보냄
return <Navigate to="/" replace />;
}
return children;
}
// Router.jsx
import ProtectedRoute from "./ProtectedRoute";
import MyPage from "./MyPage";
<Route
path="mypage"
element={
<ProtectedRoute isAllowed={false}>
<MyPage />
</ProtectedRoute>
}
/>
isAllowed가 false면 /mypage를 직접 주소창에 쳐도 Home으로 돌려보냅니다.Navigate는 런더링 이후에 조건을 확인하고, 상황에 따라 페이지 이동import { Navigate } from "react-router-dom";
const Mypage = () => {
const isLogin = false;
if (!isLogin) {
return <Navigate to="/login" replace />;
}
return <h2>마이페이지</h2>;
};