[React] React Router
개요
React Router는 React 앱에서 클라이언트 사이드 라우팅을 제공하는 라이브러리입니다. 페이지 이동 시 서버에 요청하지 않고 JavaScript로 화면을 전환합니다.
설치
npm install react-router-dom
기본 구성
폴더 구조
src/
├── App.tsx
└── pages/
├── Home.tsx
├── About.tsx
└── Users.tsx
페이지 컴포넌트 작성
// src/pages/Home.tsx
function Home() {
return <h1>홈 페이지</h1>;
}
export default Home;
// src/pages/About.tsx
function About() {
return <h1>소개 페이지</h1>;
}
export default About;
// src/pages/Users.tsx
function Users() {
return <h1>사용자 목록</h1>;
}
export default Users;
라우터 설정
// src/App.tsx
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Users from "./pages/Users";
function App() {
return (
<BrowserRouter>
{/* 네비게이션 - <a> 대신 <Link> 사용 (페이지 새로고침 방지) */}
<nav>
<Link to="/">홈</Link>
<Link to="/about">소개</Link>
<Link to="/users">사용자</Link>
</nav>
{/* 현재 URL에 맞는 컴포넌트 렌더링 */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users" element={<Users />} />
<Route path="*" element={<p>404 - 페이지를 찾을 수 없습니다</p>} />
</Routes>
</BrowserRouter>
);
}
export default App;
URL 파라미터
동적 URL에서 값을 추출합니다.
// 라우트 정의
<Route path="/users/:id" element={<UserDetail />} />
// src/pages/UserDetail.tsx
import { useParams } from "react-router-dom";
import { useState, useEffect } from "react";
function UserDetail() {
const { id } = useParams<{ id: string }>(); // URL의 :id 추출
const [user, setUser] = useState<{ name: string; email: string } | null>(null);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
return (
<div>
<h1>사용자 상세</h1>
{user ? (
<div>
<p>이름: {user.name}</p>
<p>이메일: {user.email}</p>
</div>
) : (
<p>로딩 중...</p>
)}
</div>
);
}
export default UserDetail;
// 링크에서 파라미터 포함
import { Link } from "react-router-dom";
function Users() {
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
return (
<ul>
{users.map((user) => (
<li key={user.id}>
<Link to={`/users/${user.id}`}>{user.name}</Link>
</li>
))}
</ul>
);
}
Query String (쿼리 파라미터)
URL의 ?key=value 형태의 파라미터를 다룹니다.
// URL 예: /search?q=react&page=2
import { useSearchParams } from "react-router-dom";
function Search() {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get("q") ?? ""; // null이면 ""
const page = Number(searchParams.get("page")) || 1;
return (
<div>
<input
value={query}
onChange={(e) => setSearchParams({ q: e.target.value, page: "1" })}
placeholder="검색어 입력"
/>
<p>검색어: {query}, 페이지: {page}</p>
</div>
);
}
코드로 페이지 이동 (useNavigate)
버튼 클릭이나 로직 처리 후 특정 페이지로 이동합니다.
import { useNavigate } from "react-router-dom";
function LoginPage() {
const navigate = useNavigate();
const handleLogin = async () => {
// 로그인 처리 후 메인으로 이동
await login();
navigate("/"); // 특정 경로로 이동
navigate(-1); // 뒤로 가기
navigate(1); // 앞으로 가기
navigate("/login", { replace: true }); // 이력 교체 (뒤로 가기 불가)
};
return <button onClick={handleLogin}>로그인</button>;
}
NavLink (활성 링크 스타일)
현재 URL과 일치하는 링크에 자동으로 스타일을 적용합니다.
import { NavLink } from "react-router-dom";
function Nav() {
return (
<nav>
<NavLink
to="/"
style={({ isActive }) => ({ fontWeight: isActive ? "bold" : "normal" })}
>
홈
</NavLink>
<NavLink
to="/about"
className={({ isActive }) => isActive ? "active-link" : ""}
>
소개
</NavLink>
</nav>
);
}
중첩 라우트 (Nested Routes)
레이아웃을 공유하는 중첩 구조를 만듭니다.
import { Outlet } from "react-router-dom";
// 공통 레이아웃
function Layout() {
return (
<div>
<header>공통 헤더</header>
<Outlet /> {/* 하위 라우트가 여기에 렌더링 */}
<footer>공통 푸터</footer>
</div>
);
}
// 라우트 설정
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} /> {/* 경로: / */}
<Route path="about" element={<About />} /> {/* 경로: /about */}
<Route path="users" element={<Users />} /> {/* 경로: /users */}
</Route>
</Routes>