Christmas Pikachu React Router 사용법 가이드
개발일지/React

React Router 사용법 가이드

ZI_CO 2025. 3. 5.

다음 요소들을 좀 더 자세히 다룰 예정입니다:

  1. React Router 소개 및 설치 과정 더 자세히
  2. 라우터 종류 및 차이점 상세 설명
  3. 라우팅 설정 방법 확장 예제
  4. Switch와 Route 컴포넌트의 동작 원리 상세 설명
  5. Link 컴포넌트 사용법 및 장점
  6. 컴포넌트 구조 재구성 과정 자세한 설명
  7. 더 많은 코드 예제 제공
  8. 단계별 구현 과정 설명
  9. 동적 URL 설명 추가
  10. 실제 사용 사례와 팁 제공

마크다운으로 한번에 출력하기 위해, 정보를 구조적으로 잘 정리하고 코드 블록을 포함하여 전체적인 내용을 강화할 것입니다.```markdown

React Router 완벽 가이드

목차

1. React Router 소개

1.1 React Router란?

React Router는 React 애플리케이션에서 클라이언트 사이드 라우팅을 구현하기 위한 표준 라이브러리입니다. 단일 페이지 애플리케이션(SPA)에서 여러 화면을, 페이지 새로고침 없이 전환할 수 있도록 도와줍니다.

1.2 React Router의 장점

  • 새로고침 없는 페이지 전환: 페이지 전체 새로고침 없이 컴포넌트만 교체하여 빠른 사용자 경험 제공
  • UI와 URL 동기화: 현재 화면 상태를 URL에 반영하여 북마크 및 공유 가능
  • 코드 분할: 각 라우트별로 코드를 분할하여 효율적인 로딩 가능
  • 중첩 라우팅: 복잡한 UI 구조에서 하위 라우트 구성 가능

2. 설치 및 기본 설정

2.1 설치 명령어

# npm을 사용할 경우
npm install react-router-dom

# yarn을 사용할 경우
yarn add react-router-dom

2.2 기본 컴포넌트 불러오기

// React Router v6 기준
import { 
  BrowserRouter, 
  Routes,  // Switch 대신 Routes 사용 (v6부터)
  Route,
  Link 
} from "react-router-dom";

// React Router v5 기준 (영상에서 사용)
import { 
  BrowserRouter, 
  Switch, 
  Route,
  Link 
} from "react-router-dom";

3. 라우터 종류와 차이점

React Router는 두 가지 주요 라우터 유형을 제공합니다:

3.1 BrowserRouter

<BrowserRouter>
  {/* 라우트 설정 */}
</BrowserRouter>
  • URL 형태: example.com/about, example.com/products/1
  • 장점:
    • 깔끔한 URL 구조 (# 기호 없음)
    • SEO에 더 친화적
    • 현대적인 웹 애플리케이션에 적합
  • 단점:
    • 서버 설정이 필요함 (모든 경로가 index.html로 리다이렉트되도록)
    • 정적 호스팅에서는 추가 설정 필요

3.2 HashRouter

<HashRouter>
  {/* 라우트 설정 */}
</HashRouter>
  • URL 형태: example.com/#/about, example.com/#/products/1
  • 장점:
    • 서버 설정 없이 정적 파일 서버에서도 작동
    • URL의 해시 부분은 서버로 전송되지 않음
  • 단점:
    • URL에 # 기호가 포함되어 덜 깔끔함
    • 일부 SEO 문제 발생 가능
    • 레거시 웹과의 통합 시 문제 발생 가능

대부분의 현대적인 웹 애플리케이션에서는 BrowserRouter가 권장됩니다.

4. 라우팅 설정 기본 구조

4.1 기본 구조 (v5 기준)

import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/movie">
          <Detail />
        </Route>
        <Route path="/hello">
          <h1>Hello</h1>
        </Route>
        <Route path="/" exact>
          <Home />
        </Route>
      </Switch>
    </BrowserRouter>
  );
}

export default App;

4.2 라우팅 구조 설명

  1. BrowserRouter: 전체 라우팅 시스템을 감싸는 컴포넌트
  2. Switch: 매칭되는 첫 번째 Route만 렌더링하도록 보장
  3. Route: 특정 경로에 매칭될 때 렌더링할 컴포넌트 지정
    • path: 매칭할 URL 경로
    • exact: 정확히 일치하는 경로만 매칭 (없으면 포함 관계도 매칭)
    • 내부 컴포넌트: 해당 경로일 때 렌더링할 내용

5. Switch와 Route 컴포넌트

5.1 Switch 컴포넌트

<Switch>
  {/* Route 컴포넌트들 */}
</Switch>
  • 목적: 여러 Route 중 매칭되는 첫 번째 Route만 렌더링
  • 작동 방식:
    1. 자식으로 있는 모든 Route를 검사
    2. 현재 URL과 매칭되는 첫 번째 Route를 찾음
    3. 매칭된 Route만 렌더링하고 나머지는 무시
  • 주의사항: Switch가 없으면 매칭되는 모든 Route가 동시에 렌더링될 수 있음

5.2 Route 컴포넌트

// 기본 형태
<Route path="/path">
  <Component />
</Route>

// 인라인 컴포넌트
<Route path="/hello">
  <h1>Hello</h1>
</Route>

// exact 속성 사용
<Route path="/" exact>
  <Home />
</Route>
  • 속성:
    • path: 매칭할 URL 경로 (문자열 또는 정규식)
    • exact: 정확한 경로 매칭 여부 (기본값: false)
    • strict: 끝에 슬래시(/) 포함 여부 매칭 (기본값: false)
    • sensitive: 대소문자 구분 매칭 여부 (기본값: false)
  • 중첩 가능: Route 안에 다른 Route를 중첩할 수 있음
  • path 없는 Route: 모든 경로에 매칭됨 (404 페이지 등에 유용)

6. Link 컴포넌트로 페이지 간 이동

6.1 Link 컴포넌트 기본 사용법

import { Link } from "react-router-dom";

function Navigation() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/movie">Movie Detail</Link>
    </nav>
  );
}

6.2 a 태그와 Link의 차이점

// 페이지 전체 새로고침 발생 - 권장하지 않음
<a href="/movie">영화 상세보기</a>

// 새로고침 없이 컴포넌트만 변경 - 권장
<Link to="/movie">영화 상세보기</Link>
  • a 태그:

    • 브라우저의 기본 동작으로 페이지 전체를 새로고침
    • React 애플리케이션의 상태가 초기화됨
    • 서버에 불필요한 요청 발생
  • Link 컴포넌트:

    • 클릭 이벤트를 가로채서 JavaScript로 URL 변경
    • 브라우저 주소창 URL만 변경하고 페이지는 새로고침하지 않음
    • 현재 React 애플리케이션 상태 유지
    • 필요한 컴포넌트만 다시 렌더링하여 성능 개선

6.3 Link 컴포넌트 속성

  • to: 이동할 경로 (문자열 또는 객체)
  • replace: true일 경우 history stack에 새 항목을 추가하지 않고 현재 항목을 대체
  • innerRef: DOM 요소에 대한 ref 전달

7. 컴포넌트 구조 재구성

React Router 도입 시 컴포넌트 구조를 재구성하는 것이 좋습니다.

7.1 권장 폴더 구조

src/
  ├── components/    # 재사용 가능한 UI 컴포넌트
  │   └── Movie.js   # 영화 카드 컴포넌트
  ├── routes/        # 페이지 컴포넌트
  │   ├── Home.js    # 홈 페이지 (영화 목록)
  │   └── Detail.js  # 영화 상세 페이지
  ├── App.js         # 라우팅 설정
  └── index.js       # 진입점

7.2 컴포넌트 분리 전략

  • App.js: 라우팅 설정에만 집중
  • routes/: 각 페이지 컴포넌트 관리
  • components/: 재사용 가능한 UI 컴포넌트 관리

7.3 분리된 컴포넌트 예시

App.js - 라우팅 담당

import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/movie">
          <Detail />
        </Route>
        <Route path="/" exact>
          <Home />
        </Route>
      </Switch>
    </BrowserRouter>
  );
}

export default App;

routes/Home.js - 영화 목록 페이지

import { useState, useEffect } from "react";
import Movie from "../components/Movie";

function Home() {
  const [loading, setLoading] = useState(true);
  const [movies, setMovies] = useState([]);

  const getMovies = async () => {
    const response = await (
      await fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`)
    ).json();
    setMovies(response.data.movies);
    setLoading(false);
  };

  useEffect(() => {
    getMovies();
  }, []);

  return (
    <div>
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <div>
          {movies.map((movie) => (
            <Movie
              key={movie.id}
              coverImg={movie.medium_cover_image}
              title={movie.title}
              summary={movie.summary}
              genres={movie.genres}
            />
          ))}
        </div>
      )}
    </div>
  );
}

export default Home;

routes/Detail.js - 상세 페이지

function Detail() {
  return <h1>Movie Detail</h1>;
}

export default Detail;

components/Movie.js - 영화 카드 컴포넌트

import PropTypes from "prop-types";
import { Link } from "react-router-dom";

function Movie({ coverImg, title, summary, genres }) {
  return (
    <div>
      <img src={coverImg} alt={title} />
      <h2>
        <Link to="/movie">{title}</Link>
      </h2>
      <p>{summary}</p>
      <ul>
        {genres.map((genre) => (
          <li key={genre}>{genre}</li>
        ))}
      </ul>
    </div>
  );
}

Movie.propTypes = {
  coverImg: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired,
  summary: PropTypes.string.isRequired,
  genres: PropTypes.arrayOf(PropTypes.string).isRequired
};

export default Movie;

8. 단계별 구현 가이드

8.1 초기 설정

  1. React Router 설치

    npm install react-router-dom
  2. 필요한 컴포넌트 import

    import { BrowserRouter, Switch, Route } from "react-router-dom";

8.2 라우팅 구조 설정

  1. App.js에서 라우터 설정

    function App() {
      return (
        <BrowserRouter>
          <Switch>
            <Route path="/" exact>
              <Home />
            </Route>
          </Switch>
        </BrowserRouter>
      );
    }
  2. 추가 라우트 설정

    <Switch>
      <Route path="/movie">
        <Detail />
      </Route>
      <Route path="/" exact>
        <Home />
      </Route>
    </Switch>

8.3 컴포넌트 분리 및 이동

  1. 폴더 구조 생성

    • src/components 폴더 생성
    • src/routes 폴더 생성
  2. Home 컴포넌트 이동

    • App.js에서 영화 로딩 관련 코드를 Home.js로 이동
    • Home 컴포넌트 import 및 사용
  3. Detail 컴포넌트 생성

    • 간단한 Detail 컴포넌트 생성
    • App.js에서 import 및 사용

8.4 Link 컴포넌트로 페이지 연결

  1. Link 컴포넌트 import

    import { Link } from "react-router-dom";
  2. 영화 제목에 Link 추가

    <h2>
      <Link to="/movie">{title}</Link>
    </h2>

9. 다음 단계: 동적 URL

9.1 동적 URL 필요성

현재는 모든 영화가 같은 URL(/movie)로 이동하지만, 각 영화마다 고유한 URL을 가져야 합니다.

9.2 동적 URL 구현 방법

  1. URL 파라미터 사용

    <Route path="/movie/:id">
      <Detail />
    </Route>
  2. Link에 동적 id 전달

    <Link to={`/movie/${movie.id}`}>{title}</Link>
  3. useParams 훅으로 URL 파라미터 접근

    import { useParams } from "react-router-dom";
    
    function Detail() {
      const { id } = useParams();
      // id를 사용하여 영화 상세 정보 로드
      return <h1>Movie ID: {id}</h1>;
    }

10. 고급 라우팅 기법

10.1 중첩 라우팅

라우트 내부에 또 다른 라우트를 중첩하여 복잡한 UI 구조 구현 가능

<Route path="/movies">
  <MoviesPage />
  <Switch>
    <Route path="/movies/popular">
      <PopularMovies />
    </Route>
    <Route path="/movies/new">
      <NewMovies />
    </Route>
  </Switch>
</Route>

10.2 리다이렉트

import { Redirect } from "react-router-dom";

// 조건부 리다이렉트
function ProtectedRoute() {
  const isAuthenticated = checkAuth();

  return isAuthenticated ? (
    <AdminDashboard />
  ) : (
    <Redirect to="/login" />
  );
}

// 라우트 내 리다이렉트
<Route path="/old-path">
  <Redirect to="/new-path" />
</Route>

10.3 프로그래밍 방식으로 이동

import { useHistory } from "react-router-dom";

function LoginButton() {
  const history = useHistory();

  const handleLogin = async () => {
    const success = await login();
    if (success) {
      history.push("/dashboard");
    }
  };

  return <button onClick={handleLogin}>로그인</button>;
}

10.4 라우트 보호

function PrivateRoute({ children, ...rest }) {
  const isAuthenticated = checkAuth();

  return (
    <Route
      {...rest}
      render={() => 
        isAuthenticated ? (
          children
        ) : (
          <Redirect to="/login" />
        )
      }
    />
  );
}

// 사용
<PrivateRoute path="/admin">
  <AdminPanel />
</PrivateRoute>

요약

React Router는 React 애플리케이션에서 페이지 전환을 효과적으로 관리할 수 있는 강력한 라이브러리입니다. BrowserRouter, Switch, Route, Link 등의 컴포넌트를 활용하여 사용자 경험을 향상시키고, 코드를 더 효율적으로 구성할 수 있습니다.

기본적인 라우팅 설정부터 중첩 라우팅, 동적 URL, 리다이렉트 등 다양한 기법을 활용하여 복잡한 애플리케이션의 라우팅 요구사항을 충족할 수 있습니다.

댓글