React Router는 페이지 이동을 처리하는 라이브러리다. SPA에서 URL에 따라 다른 화면을 보여준다.
npm install react-router@7
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router';
import App from './App';
createRoot(document.getElementById('root')).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);
import { Routes, Route } from 'react-router';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
function Home() {
return <h1>홈 페이지</h1>;
}
function About() {
return <h1>소개 페이지</h1>;
}
<a> 태그 대신 <Link>를 사용한다. 페이지를 새로고침하지 않는다.
import { Link } from 'react-router';
function Nav() {
return (
<nav>
<Link to="/">홈</Link>
<Link to="/about">소개</Link>
<Link to="/contact">연락처</Link>
</nav>
);
}
function App() {
return (
<div>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
);
}
URL에서 동적으로 값을 받아온다.
import { useParams } from 'react-router';
function App() {
return (
<Routes>
<Route path="/user/:id" element={<User />} />
</Routes>
);
}
function User() {
const { id } = useParams();
return <h1>사용자 ID: {id}</h1>;
}
// /user/123 접속 → 사용자 ID: 123
function App() {
return (
<Routes>
<Route path="/post/:category/:id" element={<Post />} />
</Routes>
);
}
function Post() {
const { category, id } = useParams();
return (
<div>
<p>카테고리: {category}</p>
<p>글 번호: {id}</p>
</div>
);
}
// /post/notice/5 → 카테고리: notice, 글 번호: 5
URL의 ?key=value 형태 데이터를 읽는다.
import { useSearchParams } from 'react-router';
function Search() {
const [params] = useSearchParams();
const keyword = params.get('keyword');
const page = params.get('page');
return (
<div>
<p>검색어: {keyword}</p>
<p>페이지: {page}</p>
</div>
);
}
// /search?keyword=react&page=2
function Search() {
const [params, setParams] = useSearchParams();
const change = () => {
setParams({ keyword: 'vue', page: '3' });
};
return <button onClick={change}>변경</button>;
}
버튼 클릭이나 특정 동작 후 페이지를 이동한다.
import { useNavigate } from 'react-router';
function Login() {
const navigate = useNavigate();
const login = () => {
// 로그인 처리 후
navigate('/home');
};
const back = () => {
navigate(-1); // 뒤로가기
};
return (
<div>
<button onClick={login}>로그인</button>
<button onClick={back}>뒤로</button>
</div>
);
}
레이아웃 안에 다른 페이지를 표시한다.
import { Outlet } from 'react-router';
function App() {
return (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
</Route>
</Routes>
);
}
function Layout() {
return (
<div>
<header>
<nav>
<Link to="/">홈</Link>
<Link to="/about">소개</Link>
<Link to="/contact">연락처</Link>
</nav>
</header>
<main>
<Outlet />
</main>
<footer>푸터</footer>
</div>
);
}
일치하는 경로가 없을 때 표시한다.
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
);
}
function NotFound() {
return (
<div>
<h1>404 - 페이지를 찾을 수 없습니다</h1>
<Link to="/">홈으로 가기</Link>
</div>
);
}
현재 페이지의 링크를 강조한다.
import { NavLink } from 'react-router';
function Nav() {
return (
<nav>
<NavLink
to="/"
style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}
>
홈
</NavLink>
<NavLink
to="/about"
className={({ isActive }) => isActive ? 'active' : ''}
>
소개
</NavLink>
</nav>
);
}
파일을 나누어 관리한다.
import Home from './pages/Home';
import About from './pages/About';
import User from './pages/User';
export const routes = [
{ path: '/', element: <Home /> },
{ path: '/about', element: <About /> },
{ path: '/user/:id', element: <User /> }
];
import { Routes, Route } from 'react-router';
import { routes } from './routes';
function App() {
return (
<Routes>
{routes.map((route, i) => (
<Route key={i} path={route.path} element={route.element} />
))}
</Routes>
);
}
import { Routes, Route, Link, useParams } from 'react-router';
const posts = [
{ id: 1, title: '첫 글', content: '안녕하세요' },
{ id: 2, title: '두 번째 글', content: 'React 공부 중' },
{ id: 3, title: '세 번째 글', content: '재미있어요' }
];
function App() {
return (
<div>
<nav>
<Link to="/">홈</Link>
<Link to="/posts">글 목록</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/posts" element={<PostList />} />
<Route path="/posts/:id" element={<PostDetail />} />
</Routes>
</div>
);
}
function Home() {
return <h1>블로그 홈</h1>;
}
function PostList() {
return (
<div>
<h2>글 목록</h2>
{posts.map(post => (
<div key={post.id}>
<Link to={`/posts/${post.id}`}>{post.title}</Link>
</div>
))}
</div>
);
}
function PostDetail() {
const { id } = useParams();
const post = posts.find(p => p.id === Number(id));
if (!post) return <div>글을 찾을 수 없습니다</div>;
return (
<div>
<h2>{post.title}</h2>
<p>{post.content}</p>
<Link to="/posts">목록으로</Link>
</div>
);
}
로그인한 사용자만 접근할 수 있는 페이지를 만든다.
import { Navigate } from 'react-router';
function ProtectedRoute({ children }) {
const isLoggedIn = false; // 실제로는 상태 관리에서 가져옴
if (!isLoggedIn) {
return <Navigate to="/login" />;
}
return children;
}
function App() {
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/mypage"
element={
<ProtectedRoute>
<MyPage />
</ProtectedRoute>
}
/>
</Routes>
);
}
BrowserRouter로 앱을 감싼다Routes와 Route로 경로를 설정한다Link로 페이지를 이동한다useParams로 URL 파라미터를 가져온다useNavigate로 프로그래밍 방식 이동을 한다Outlet으로 중첩 라우트를 만든다