웹사이트를 만들 때 여러 페이지를 오갈 필요가 있다. 예를 들어 '홈' → '소개' → '게시판' 이런식으로.
React는 기본적으로 싱글 페이지 애플리케이션(SPA)이다. 페이지를 새로고침하지 않고도 콘텐츠를 바꾼다는 뜻이다. React Router Dom은 이렇게 다양한 페이지를 관리하고, URL을 변경하며, 각 URL에 맞는 컴포넌트를 보여주는 라이브러리다.
쉽게 말해, 사용자가 /about에 접속하면 About 페이지를 보여주고, /contact에 접속하면 Contact 페이지를 보여주는 것이 바로 라우팅이다.
먼저 프로젝트에 react-router-dom을 설치해야 한다.
npm install react-router-dom
앱 전체를 감싸는 최상위 컴포넌트이다. 라우팅 기능을 활성화한다.
여러 Route를 담는 컨테이너다. "여기 안에서 경로를 매칭할 거야"라는 뜻이다.
특정 URL 경로와 컴포넌트를 연결한다. /about 경로면 About 컴포넌트를 보여준다는 식의 규칙을 정의한다.
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 (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
export default App;
이제 사용자가 /, /about, /contact URL을 방문할 수 있다.
<a> 태그 대신 <Link> 컴포넌트를 사용하자. 일반 링크는 페이지를 새로고침하지만, Link는 SPA 방식으로 빠르게 전환된다.
Navbar.js
import { Link } from 'react-router-dom';
export default function Navbar() {
return (
<nav>
<Link to="/">홈</Link>
<Link to="/about">소개</Link>
<Link to="/contact">연락처</Link>
</nav>
);
}
그리고 App.js에 추가하자.
import Navbar from './components/Navbar';
function App() {
return (
<BrowserRouter>
<Navbar />
<Routes>
{/* routes... */}
</Routes>
</BrowserRouter>
);
}
게시글 ID를 URL에 포함시켜 특정 게시글을 보여주고 싶다면?
App.js
<Route path="/post/:id" element={<Post />} />
pages/Post.js
import { useParams } from 'react-router-dom';
export default function Post() {
const { id } = useParams();
return <h1>게시글 {id}번입니다!</h1>;
}
이제 /post/1, /post/2 같은 URL에서 각각 다른 게시글 ID를 받을 수 있다.
버튼을 클릭했을 때 프로그래밍으로 페이지를 이동하고 싶다면:
import { useNavigate } from 'react-router-dom';
export default function LoginPage() {
const navigate = useNavigate();
const handleLogin = () => {
// 로그인 로직
navigate('/dashboard'); // 대시보드로 이동
};
return <button onClick={handleLogin}>로그인</button>;
}
더 복잡한 구조를 원한다면? 예를 들어, /dashboard 안에 /dashboard/profile, /dashboard/settings 같은 서브 페이지가 있다면:
App.js
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
pages/Dashboard.js
import { Outlet, Link } from 'react-router-dom';
export default function Dashboard() {
return (
<div>
<h1>대시보드</h1>
<nav>
<Link to="profile">프로필</Link>
<Link to="settings">설정</Link>
</nav>
<Outlet /> {/* 자식 라우트가 여기 렌더링됨 */}
</div>
);
}
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
// 페이지 컴포넌트들
function Home() {
return (
<div>
<h1>블로그 홈</h1>
<p>최신 글들을 확인하세요</p>
</div>
);
}
function PostList() {
const posts = [
{ id: 1, title: 'React 배우기' },
{ id: 2, title: 'Router 이해하기' },
{ id: 3, title: '상태 관리하기' }
];
return (
<div>
<h1>게시글 목록</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
<Link to={`/post/${post.id}`}>{post.title}</Link>
</li>
))}
</ul>
</div>
);
}
function PostDetail() {
const { id } = useParams();
return <h1>게시글 {id}번</h1>;
}
// 앱
function App() {
return (
<BrowserRouter>
<nav style={{ marginBottom: '20px' }}>
<Link to="/">홈</Link> | <Link to="/posts">게시글</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/posts" element={<PostList />} />
<Route path="/post/:id" element={<PostDetail />} />
</Routes>
</BrowserRouter>
);
}
export default App;