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메인 페이지
/newNew새 일기 작성
/diary/:idDiary일기 상세보기 (예: /diary/1, /diary/123)
/edit/:idEdit일기 수정 (예: /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개의 링크가 보이죠?

이제 링크를 클릭하면 페이지가 전환돼요! 🎉

“그냥 <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="*"는 “위의 모든 경로와 일치하지 않으면” 이라는 뜻이에요.

네! useNavigate를 쓰면 돼요:

const navigate = useNavigate();

const handleSubmit = () => {
    // 일기 저장 로직...
    navigate('/');  // 저장 후 홈으로 이동
};

폼을 제출하거나 로그인 후 리다이렉트할 때 유용해요.

Q4. URL 파라미터 외에 데이터를 전달하려면?

state를 사용할 수 있어요:

// 데이터와 함께 이동
navigate('/diary/1', { state: { emotion: '행복' } });

// 받는 쪽
const location = useLocation();
console.log(location.state.emotion);  // "행복"

정리하며

오늘 2편에서 배운 내용을 정리하면:

핵심만 기억하세요:

  1. 🚦 App.js가 교통경찰 역할 (Routes와 Route로 URL 매칭)
  2. 🔗 Link로 페이지 이동 (<a>보다 빠름)
  3. 📍 :id는 동적 파라미터 (useParams로 가져옴)
  4. ⬅️ navigate로 프로그래밍 방식 이동 가능

다음 편에서는 본격적으로 Editor 컴포넌트를 만들면서 State 관리를 배워볼 거예요. 사용자가 입력하는 날짜, 감정, 일기 내용을 어떻게 저장하고 관리하는지 알아봅시다!


시리즈 네비게이션