[이제와서 시작하는 React 마스터하기 #9] React Router - 페이지 이동하기
React Day 9 - 버튼을 클릭하면 다른 페이지로 이동하게 만들고 싶으신가요? React Router로 SPA(Single Page Application)를 만들어봅시다!
오늘 배울 내용
- ✅ React Router가 뭔가요?
- ✅ 설치하고 기본 설정하기
- ✅ 페이지 이동하기: Link, useNavigate
- ✅ URL 파라미터 사용하기: useParams
- ✅ 실전 예제: 블로그 앱 만들기
시작하기 전에
이전에 배운 내용을 기억하시나요?
- Day 6: 조건부/리스트 렌더링에서 동적 UI를 만들었어요
- Day 7: Context API에서 전역 상태를 관리했어요
- Day 8: Custom Hooks에서 로직을 재사용했어요
오늘은 여러 페이지를 가진 웹사이트를 만드는 방법을 배워봅시다!
React Router가 뭔가요?
React Router는 React로 여러 페이지를 가진 웹사이트를 만들 때 사용하는 도구예요.
일상 비유 📖
웹사이트를 책이라고 생각해보세요:
일반 웹사이트 (옛날 방식):
1
2
3
4
5
목차 페이지 → 1장 읽기
다시 목차로 돌아가서 → 2장 읽기
또 목차로 돌아가서 → 3장 읽기
매번 목차로 돌아가야 해요! (페이지 새로고침)
SPA with React Router (현대 방식):
1
2
3
4
책을 펼쳐놓고
1장 → 2장 → 3장 → 빠르게 넘기기
목차로 돌아갈 필요 없이 바로바로 이동! (새로고침 없음)
React Router를 사용하면:
- ✅ 페이지 새로고침 없이 화면 전환
- ✅ 빠른 페이지 이동
- ✅ 뒤로가기/앞으로가기 버튼 작동
- ✅ URL이 바뀌어서 북마크 가능
설치하기
터미널에서 React Router를 설치해요:
1
npm install react-router-dom
설치가 끝나면 사용 준비 완료! 🎉
기본 사용법
Step 1: BrowserRouter로 감싸기
App.js 또는 index.js에서 전체 앱을 BrowserRouter로 감싸요:
1
2
3
4
5
6
7
8
9
10
11
12
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
설명: BrowserRouter는 라우팅 기능을 활성화해주는 “감싸는 상자”예요.
Step 2: 페이지 컴포넌트 만들기
간단한 페이지 3개를 만들어봅시다:
1
2
3
4
5
6
7
8
9
10
11
// src/pages/Home.js
function Home() {
return (
<div style=>
<h1>🏠 홈 페이지</h1>
<p>React Router에 오신 것을 환영합니다!</p>
</div>
);
}
export default Home;
1
2
3
4
5
6
7
8
9
10
11
// src/pages/About.js
function About() {
return (
<div style=>
<h1>ℹ️ 소개 페이지</h1>
<p>이 사이트는 React Router 데모입니다.</p>
</div>
);
}
export default About;
1
2
3
4
5
6
7
8
9
10
11
// src/pages/Contact.js
function Contact() {
return (
<div style=>
<h1>📧 연락처 페이지</h1>
<p>이메일: contact@example.com</p>
</div>
);
}
export default Contact;
Step 3: Routes 설정하기
App.js에서 경로(Route)를 설정해요:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// src/App.js
import { Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<div>
{/* 네비게이션 바 */}
<nav style=>
<Link to="/" style=>홈</Link>
<Link to="/about" style=>소개</Link>
<Link to="/contact" style=>연락처</Link>
</nav>
{/* 라우트 설정 */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
);
}
export default App;
해보기:
- 위 코드를 복사해서 실행해보세요
- 네비게이션 링크를 클릭해보세요
- 페이지가 새로고침 없이 바뀌는지 확인하세요!
동작 원리:
<Route path="/" element={<Home />} />: “/” 주소일 때 Home 컴포넌트 보여주기<Link to="/">: “/” 주소로 이동하는 링크 (새로고침 없음!)
Link vs a 태그
❌ 일반 a 태그 (사용하지 마세요!)
1
<a href="/">홈</a> // 페이지 새로고침됨!
✅ Link 컴포넌트 (React Router)
1
<Link to="/">홈</Link> // 새로고침 없음!
차이점:
<a>태그: 페이지 전체가 새로고침 → 느림 😢<Link>: 필요한 부분만 바뀜 → 빠름 😊
실습 1: 네비게이션 바 스타일링
좀 더 예쁜 네비게이션 바를 만들어봅시다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<div>
{/* 네비게이션 바 */}
<nav style=>
<div style=>
<Link
to="/"
style=
>
🏠 홈
</Link>
<Link
to="/about"
style=
>
ℹ️ 소개
</Link>
<Link
to="/contact"
style=
>
📧 연락처
</Link>
</div>
</nav>
{/* 라우트 */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
);
}
export default App;
useNavigate: 프로그래밍 방식으로 이동하기
버튼을 클릭했을 때 페이지를 이동하고 싶다면? useNavigate를 사용하세요!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
const goToAbout = () => {
navigate('/about');
};
const goBack = () => {
navigate(-1); // 뒤로가기
};
return (
<div style=>
<h1>🏠 홈 페이지</h1>
<p>React Router에 오신 것을 환영합니다!</p>
<div style=>
<button
onClick={goToAbout}
style=
>
소개 페이지로 이동
</button>
<button
onClick={goBack}
style=
>
뒤로가기
</button>
</div>
</div>
);
}
export default Home;
사용 예시:
navigate('/about')- /about 페이지로 이동navigate(-1)- 뒤로가기navigate(1)- 앞으로가기navigate('/about', { replace: true })- 히스토리 남기지 않고 이동
동적 라우팅: useParams
URL에 변수를 넣고 싶을 때 사용해요! 예를 들어 블로그 글마다 다른 ID를 가진 경우:
1
2
3
4
5
// App.js
<Routes>
<Route path="/" element={<Home />} />
<Route path="/post/:id" element={<Post />} />
</Routes>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// pages/Post.js
import { useParams } from 'react-router-dom';
function Post() {
const { id } = useParams(); // URL에서 id 가져오기
// 가상의 블로그 데이터
const posts = {
'1': { title: 'React 입문', content: 'React를 시작해봅시다!' },
'2': { title: 'React Router', content: 'Router로 페이지를 만들어요!' },
'3': { title: 'Context API', content: 'Context로 상태를 관리해요!' }
};
const post = posts[id];
if (!post) {
return <div style=>존재하지 않는 글입니다.</div>;
}
return (
<div style=>
<h1>📝 {post.title}</h1>
<p>{post.content}</p>
<p style=>Post ID: {id}</p>
</div>
);
}
export default Post;
해보기:
- 주소창에
/post/1,/post/2,/post/3을 입력해보세요 - 각 ID에 맞는 내용이 표시되는지 확인하세요!
실습 2: 블로그 앱 만들기
모든 내용을 종합한 블로그 앱을 만들어봅시다!
1. 홈 페이지 (글 목록)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// pages/Home.js
import { Link } from 'react-router-dom';
function Home() {
const posts = [
{ id: 1, title: 'React 입문', preview: 'React를 시작해봅시다!' },
{ id: 2, title: 'React Router', preview: 'Router로 페이지를 만들어요!' },
{ id: 3, title: 'Context API', preview: 'Context로 상태를 관리해요!' }
];
return (
<div style=>
<h1>📚 블로그 글 목록</h1>
<div style=>
{posts.map(post => (
<Link
key={post.id}
to={`/post/${post.id}`}
style=
>
<div
style=
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#e3f2fd';
e.currentTarget.style.borderColor = '#2196f3';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = '#f5f5f5';
e.currentTarget.style.borderColor = '#e0e0e0';
}}
>
<h2 style=>{post.title}</h2>
<p style=>{post.preview}</p>
</div>
</Link>
))}
</div>
</div>
);
}
export default Home;
2. 글 상세 페이지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// pages/Post.js
import { useParams, useNavigate } from 'react-router-dom';
function Post() {
const { id } = useParams();
const navigate = useNavigate();
const posts = {
'1': {
title: 'React 입문',
content: 'React는 Facebook에서 만든 JavaScript 라이브러리입니다. 컴포넌트 기반으로 UI를 구성하며, Virtual DOM을 사용해 효율적인 렌더링이 가능합니다.',
date: '2025-01-01'
},
'2': {
title: 'React Router',
content: 'React Router는 SPA(Single Page Application)를 만들 때 사용하는 라이브러리입니다. 페이지 새로고침 없이 URL을 변경하고 컴포넌트를 렌더링할 수 있습니다.',
date: '2025-01-02'
},
'3': {
title: 'Context API',
content: 'Context API는 Props Drilling 문제를 해결하기 위한 React의 기능입니다. 전역 상태를 관리하고, 깊이 중첩된 컴포넌트에 데이터를 쉽게 전달할 수 있습니다.',
date: '2025-01-03'
}
};
const post = posts[id];
if (!post) {
return (
<div style=>
<h1>😢 존재하지 않는 글입니다</h1>
<button
onClick={() => navigate('/')}
style=
>
홈으로 돌아가기
</button>
</div>
);
}
return (
<div style=>
<button
onClick={() => navigate('/')}
style=
>
← 목록으로
</button>
<article>
<h1 style=>
📝 {post.title}
</h1>
<p style=>
{post.date}
</p>
<div style=>
{post.content}
</div>
</article>
<div style=>
<p style=>
💡 이 글이 도움이 되셨나요?
</p>
<p style=>
다른 글도 확인해보세요!
</p>
</div>
</div>
);
}
export default Post;
3. 전체 App 구성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// App.js
import { Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import Post from './pages/Post';
import About from './pages/About';
function App() {
return (
<div>
{/* 네비게이션 */}
<nav style=>
<div style=>
<Link
to="/"
style=
>
📚 My Blog
</Link>
<div style=>
<Link
to="/"
style=
>
홈
</Link>
<Link
to="/about"
style=
>
소개
</Link>
</div>
</div>
</nav>
{/* 라우트 */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/post/:id" element={<Post />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
);
}
export default App;
해보기:
- 홈 페이지에서 글 카드를 클릭해보세요
- 글 상세 페이지에서 “목록으로” 버튼을 클릭해보세요
- 주소창의 URL이 바뀌는 것을 확인하세요
- 브라우저의 뒤로가기 버튼도 작동하는지 확인하세요!
404 페이지 만들기
존재하지 않는 URL에 접근했을 때 보여줄 페이지를 만들어봅시다:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// pages/NotFound.js
import { useNavigate } from 'react-router-dom';
function NotFound() {
const navigate = useNavigate();
return (
<div style=>
<h1 style=>404</h1>
<h2 style=>
페이지를 찾을 수 없습니다
</h2>
<p style=>
요청하신 페이지가 존재하지 않습니다.
</p>
<button
onClick={() => navigate('/')}
style=
>
홈으로 돌아가기
</button>
</div>
);
}
export default NotFound;
1
2
3
4
5
6
7
// App.js에 추가
<Routes>
<Route path="/" element={<Home />} />
<Route path="/post/:id" element={<Post />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} /> {/* 모든 잘못된 경로 */}
</Routes>
흔한 실수와 해결 방법
실수 1: BrowserRouter로 감싸지 않음
❌ 잘못된 코드:
1
2
// index.js
root.render(<App />); // BrowserRouter 없음!
⚠️ 에러: “useNavigate() may be used only in the context of a Router component”
✅ 올바른 코드:
1
2
3
4
5
6
// index.js
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
실수 2: a 태그 사용
❌ 잘못된 코드:
1
<a href="/about">소개</a> // 페이지 새로고침됨!
✅ 올바른 코드:
1
<Link to="/about">소개</Link> // 새로고침 없음!
실수 3: Routes 안에 Route가 아닌 다른 요소
❌ 잘못된 코드:
1
2
3
4
<Routes>
<div>헤더</div> // Routes 안에는 Route만!
<Route path="/" element={<Home />} />
</Routes>
✅ 올바른 코드:
1
2
3
4
<div>헤더</div> {/* Routes 밖에 */}
<Routes>
<Route path="/" element={<Home />} />
</Routes>
정리
오늘은 React Router로 여러 페이지를 가진 앱을 만드는 방법을 배웠어요!
핵심 포인트 ✅
기본 개념:
- React Router: 페이지 새로고침 없이 화면 전환
- SPA (Single Page Application): 하나의 페이지에서 모든 것을 처리
핵심 컴포넌트:
<BrowserRouter>: 라우팅 기능 활성화<Routes>: 라우트 목록을 감싸는 컨테이너<Route>: 경로와 컴포넌트 연결<Link>: 페이지 이동 링크 (새로고침 없음)
핵심 Hooks:
useNavigate(): 프로그래밍 방식으로 페이지 이동useParams(): URL 파라미터 가져오기
오늘 배운 내용 체크 ✅
- React Router가 무엇인지 이해했나요?
- BrowserRouter로 앱을 감쌌나요?
- Link로 페이지 이동을 구현했나요?
- useNavigate로 버튼 클릭 시 이동을 구현했나요?
- useParams로 동적 라우팅을 구현했나요?
- 404 페이지를 만들어봤나요?
숙제 📚
- 프로필 페이지 추가:
/profile/:username경로 만들기 - 검색 페이지: 검색어를 URL에 포함시키기
- 카테고리별 필터링:
/category/:name경로로 카테고리별 글 표시
다음 단계
다음 포스트에서는 폼 처리와 유효성 검증을 배워봅니다! 사용자 입력을 받고, 검증하고, 제출하는 방법을 알아봐요.
“늦었다고 생각할 때가 가장 빠를 때입니다. React Router 마스터! 🎉”
React 완벽 가이드 시리즈
- React란 무엇인가?
- 첫 React 앱 만들기
- useState - 클릭하면 바뀌는 화면
- Props - 컴포넌트끼리 대화하기
- useEffect - 컴포넌트 생명주기
- 조건부/리스트 렌더링
- Context API - Props 지옥에서 탈출
- Custom Hooks - 반복되는 로직 재사용하기
- React Router - 페이지 이동하기 ← 현재 글
- 폼 처리와 유효성 검증
- React 성능 최적화
- 에러 바운더리와 Suspense
- 상태 관리 라이브러리
- 서버 상태 관리
- React와 TypeScript
- Next.js 입문
- React 테스팅 전략
- 고급 패턴과 베스트 프랙티스
- 실전 프로젝트
- React 배포와 DevOps
