React 감정 일기장 만들기 2편 - React Router로 페이지 만들기
1편에서 React 프로젝트를 만들고 기본 구조를 이해했어요. 이제 본격적으로 여러 페이지를 만들어볼 차례예요!
일반 웹사이트처럼 /home, /diary, /new 이런 URL로 다른 화면을 보여주려면 React Router가 필요해요. 오늘은 이걸 사용해서 4개의 페이지를 만들고 연결하는 방법을 배워봅시다.
이번 편에서 배울 내용
- ✅ App.js의 역할 (교통 정리하기)
- ✅ Routes와 Route 컴포넌트 사용법
- ✅ Home, New, Diary, Edit 페이지 생성
- ✅ Link 컴포넌트로 페이지 이동하기
- ✅ 동적 라우팅 (:id 파라미터) 이해하기
전체 구조 먼저 보기
오늘 만들 구조를 다이어그램으로 먼저 볼게요:
graph TD
A["index.html<br/>(빈 HTML 파일)"] --> B["index.js<br/>(React 앱 시작점)"]
B --> C["App.js<br/>(라우터 - 교통정리)"]
C --> D["Home 페이지<br/>(/)"]
C --> E["New 페이지<br/>(/new)"]
C --> F["Diary 페이지<br/>(/diary/:id)"]
C --> G["Edit 페이지<br/>(/edit/:id)"]
style A fill:#e1f5ff
style B fill:#ffe1e1
style C fill:#fff4e1
style D fill:#e1ffe1
style E fill:#e1ffe1
style F fill:#e1ffe1
style G fill:#e1ffe1
App.js가 교통경찰처럼 “이 URL로 오면 이 페이지 보여줘!” 하고 정리하는 거예요.
페이지 파일 만들기
먼저 페이지 파일들을 만들어야 해요. 터미널에서 이 명령어들을 실행하세요:
# src/page 폴더 생성
mkdir src/page
# 윈도우 사용자는 이렇게
# mkdir src\page
이제 VS Code에서 src/page 폴더 안에 4개의 파일을 만들어주세요:
1. Home.js - 메인 페이지
const Home = () => {
return (
<div>
<h1>Home 페이지</h1>
<p>감정 일기장 메인 페이지입니다.</p>
</div>
);
};
export default Home;
2. New.js - 새 일기 작성 페이지
const New = () => {
return (
<div>
<h1>New 페이지</h1>
<p>새로운 일기를 작성하는 페이지입니다.</p>
</div>
);
};
export default New;
3. Diary.js - 일기 상세보기 페이지
import { useParams } from 'react-router-dom';
const Diary = () => {
const { id } = useParams();
return (
<div>
<h1>Diary 페이지</h1>
<p>{id}번 일기를 보고 있습니다.</p>
</div>
);
};
export default Diary;
4. Edit.js - 일기 수정 페이지
import { useParams } from 'react-router-dom';
const Edit = () => {
const { id } = useParams();
return (
<div>
<h1>Edit 페이지</h1>
<p>{id}번 일기를 수정하는 페이지입니다.</p>
</div>
);
};
export default Edit;
useParams()가 뭔지 궁금하시죠? URL에서 :id 부분의 값을 가져오는 React Router의 훅이에요. 나중에 자세히 설명할게요!
App.js에 라우터 설정하기
이제 src/App.js를 열어서 라우터를 설정해볼게요. 기존 코드를 전부 지우고 이렇게 작성하세요:
import { Routes, Route } from 'react-router-dom';
import Home from './page/Home';
import New from './page/New';
import Diary from './page/Diary';
import Edit from './page/Edit';
import './App.css';
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary/:id" element={<Diary />} />
<Route path="/edit/:id" element={<Edit />} />
</Routes>
</div>
);
}
export default App;
코드를 하나씩 뜯어볼게요:
Import 부분
import { Routes, Route } from 'react-router-dom';
Routes: 여러 개의 Route를 묶어주는 컨테이너Route: 개별 경로와 컴포넌트를 연결
import Home from './page/Home';
import New from './page/New';
import Diary from './page/Diary';
import Edit from './page/Edit';
방금 만든 4개의 페이지를 불러와요.
Routes와 Route 사용하기
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary/:id" element={<Diary />} />
<Route path="/edit/:id" element={<Edit />} />
</Routes>
이게 핵심이에요! 표로 정리하면:
| URL 주소 | 보여줄 페이지 | 설명 |
|---|---|---|
/ | Home | 메인 페이지 |
/new | New | 새 일기 작성 |
/diary/:id | Diary | 일기 상세보기 (예: /diary/1, /diary/123) |
/edit/:id | Edit | 일기 수정 (예: /edit/1, /edit/123) |
:id 부분이 재밌는데요, 이건 “여기에 아무 값이나 들어올 수 있어”라는 뜻이에요.
예를 들어:
/diary/1→ Diary 페이지 (id=1)/diary/123→ Diary 페이지 (id=123)/diary/abc→ Diary 페이지 (id=abc)
다 같은 Diary 페이지로 가지만, id 값은 다르죠. 이 값을 useParams()로 가져와서 “몇 번 일기를 보는지” 알 수 있어요.
페이지 이동 버튼 만들기
이제 브라우저 주소창에 직접 URL을 치지 않고도 페이지를 이동할 수 있게 네비게이션 버튼을 만들어볼게요.
App.js에 Link 버튼들을 추가하세요:
import { Routes, Route, Link } from 'react-router-dom'; // Link 추가!
import Home from './page/Home';
import New from './page/New';
import Diary from './page/Diary';
import Edit from './page/Edit';
import './App.css';
function App() {
return (
<div className="App">
{/* 네비게이션 메뉴 추가 */}
<nav style={{
padding: '20px',
borderBottom: '2px solid #ccc',
marginBottom: '20px'
}}>
<Link to="/" style={{ marginRight: '10px' }}>Home</Link>
<Link to="/new" style={{ marginRight: '10px' }}>New</Link>
<Link to="/diary/1" style={{ marginRight: '10px' }}>Diary(1번)</Link>
<Link to="/edit/1">Edit(1번)</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary/:id" element={<Diary />} />
<Route path="/edit/:id" element={<Edit />} />
</Routes>
</div>
);
}
export default App;
파일을 저장하고 브라우저를 보세요. 상단에 4개의 링크가 보이죠?
이제 링크를 클릭하면 페이지가 전환돼요! 🎉
Link vs a 태그
“그냥 <a href="/"> 쓰면 안 돼요?” 하고 물어볼 수 있어요.
차이점을 볼게요:
// ❌ 이렇게 쓰면 안 돼요
<a href="/">Home</a> // 페이지 전체를 새로고침함
// ✅ 이렇게 써야 해요
<Link to="/">Home</Link> // 필요한 부분만 바꿔서 빠름
<a> 태그를 쓰면 페이지를 통째로 새로고침해요. 그러면 React 앱이 처음부터 다시 시작돼서 느려요.
<Link>는 필요한 컴포넌트만 바꿔서 훨씬 빠르고 부드럽게 전환돼요. 이게 바로 **SPA(Single Page Application)**의 장점이에요!
동적 라우팅 자세히 알아보기
아까 useParams()를 썼죠? 이걸 좀 더 자세히 봅시다.
Diary.js에서 ID 사용하기
import { useParams } from 'react-router-dom';
const Diary = () => {
const { id } = useParams();
return (
<div>
<h1>Diary 페이지</h1>
<p>{id}번 일기를 보고 있습니다.</p>
{/* 실제로는 이 id로 데이터베이스에서 일기를 가져와요 */}
<div style={{
padding: '20px',
backgroundColor: '#f0f0f0',
borderRadius: '8px',
marginTop: '20px'
}}>
<h3>일기 내용 (예시)</h3>
<p>오늘은 날씨가 좋았다. 기분이 좋아서 산책을 했다...</p>
<p><small>작성일: 2024-12-{id}일</small></p>
</div>
</div>
);
};
export default Diary;
이제 다른 번호로 테스트해볼까요? 브라우저 주소창에:
http://localhost:3000/diary/1입력 → “1번 일기”http://localhost:3000/diary/999입력 → “999번 일기”
번호가 바뀌는 게 보이죠?
여러 개의 파라미터
나중에 이런 것도 가능해요:
<Route path="/diary/:year/:month/:id" element={<Diary />} />
const Diary = () => {
const { year, month, id } = useParams();
return (
<div>
<h1>{year}년 {month}월의 {id}번 일기</h1>
</div>
);
};
URL: /diary/2024/12/5 → “2024년 12월의 5번 일기”
뒤로가기 버튼 만들기
페이지에 뒤로가기 버튼도 추가해볼게요. Diary.js를 수정하세요:
import { useParams, useNavigate } from 'react-router-dom';
const Diary = () => {
const { id } = useParams();
const navigate = useNavigate();
const handleGoBack = () => {
navigate(-1); // 이전 페이지로!
};
const handleGoHome = () => {
navigate('/'); // 홈으로!
};
return (
<div>
<h1>Diary 페이지</h1>
<p>{id}번 일기를 보고 있습니다.</p>
<div style={{ marginTop: '20px' }}>
<button onClick={handleGoBack} style={{ marginRight: '10px' }}>
뒤로가기
</button>
<button onClick={handleGoHome}>
홈으로
</button>
</div>
</div>
);
};
export default Diary;
navigate(-1): 브라우저의 뒤로가기 버튼과 똑같아요navigate('/'): 특정 경로로 이동해요navigate(-2): 두 페이지 뒤로 가요
확인하기
여기까지 잘 따라오셨나요? 다음 항목들을 확인해보세요:
✅ 페이지 생성 확인
src/page폴더에 4개의 파일 (Home.js, New.js, Diary.js, Edit.js) 생성됨
✅ 라우팅 동작 확인
/접속 시 Home 페이지 표시/new접속 시 New 페이지 표시/diary/1접속 시 Diary 페이지에 “1번 일기” 표시/edit/1접속 시 Edit 페이지에 “1번 일기” 표시
✅ 네비게이션 확인
- 상단 링크 클릭 시 페이지 전환됨
- 페이지 새로고침 없이 부드럽게 전환됨
- 브라우저 뒤로가기/앞으로가기 버튼 정상 동작
✅ 동적 라우팅 확인
/diary/1,/diary/2,/diary/999모두 같은 페이지로 이동- 각각 다른 ID 값이 표시됨
자주 묻는 질문
Q1. Route 순서가 중요한가요?
네, 때로는 중요해요! React Router는 위에서 아래로 순서대로 매칭을 시도해요.
// ❌ 이렇게 하면 안 돼요
<Route path="/diary/:id" element={<Diary />} />
<Route path="/diary/new" element={<DiaryNew />} />
// "/diary/new"를 입력하면 첫 번째 Route에 매칭돼서
// Diary 컴포넌트가 나타나고 id="new"가 돼요
// ✅ 이렇게 해야 해요
<Route path="/diary/new" element={<DiaryNew />} />
<Route path="/diary/:id" element={<Diary />} />
// 구체적인 경로를 먼저 쓰세요!
Q2. 404 페이지는 어떻게 만들어요?
이렇게 하면 돼요:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary/:id" element={<Diary />} />
<Route path="/edit/:id" element={<Edit />} />
<Route path="*" element={<NotFound />} /> {/* 404 페이지 */}
</Routes>
path="*"는 “위의 모든 경로와 일치하지 않으면” 이라는 뜻이에요.
Q3. Link 말고 프로그래밍 방식으로 이동할 수 있나요?
네! useNavigate를 쓰면 돼요:
const navigate = useNavigate();
const handleSubmit = () => {
// 일기 저장 로직...
navigate('/'); // 저장 후 홈으로 이동
};
폼을 제출하거나 로그인 후 리다이렉트할 때 유용해요.
Q4. URL 파라미터 외에 데이터를 전달하려면?
state를 사용할 수 있어요:
// 데이터와 함께 이동
navigate('/diary/1', { state: { emotion: '행복' } });
// 받는 쪽
const location = useLocation();
console.log(location.state.emotion); // "행복"
정리하며
오늘 2편에서 배운 내용을 정리하면:
핵심만 기억하세요:
- 🚦 App.js가 교통경찰 역할 (Routes와 Route로 URL 매칭)
- 🔗 Link로 페이지 이동 (
<a>보다 빠름) - 📍 :id는 동적 파라미터 (useParams로 가져옴)
- ⬅️ navigate로 프로그래밍 방식 이동 가능
다음 편에서는 본격적으로 Editor 컴포넌트를 만들면서 State 관리를 배워볼 거예요. 사용자가 입력하는 날짜, 감정, 일기 내용을 어떻게 저장하고 관리하는지 알아봅시다!
시리즈 네비게이션
- 1편: React 프로젝트 시작하기 - 기본 구조 이해
- 2편: React Router로 페이지 만들기 ← 현재 글
- 3편: State로 데이터 관리하기 (다음 편)
- 4편: 재사용 가능한 컴포넌트 만들기
- 5편: 전체 앱 연결 및 데이터 관리