1. 라우팅이란???🤔

웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것을 의미한다.

만약 자신이 애플리케이션을 만들 때 하나의 페이지로 충분한 것도 있지만, 블로그 같은 애플리케이션을 만든다면 여러 페이지가 필요할 것이다. 이렇게 여러 페이지로 구성된 웹 애플리케이션을 만들 때 페이지 별로 컴포넌트들을 분리해가면서 프로젝트를 관리하기 위해 필요한 것이 라우팅 시스템이다.

리액트에서 라우트 시스템을 구축하기 위해 사용할 수 있는 선택지는 크게 두 가지다!

  • 리액트 라우터(React Router) : 이 라이브러리는 리액트의 라우팅 관련 라이브러리들 중에서 가장 오래됐고, 가장 많이 사용하고 있다. 컴포넌트 기반으로 라우팅 시스템을 설정할 수 있다.

  • Next.js : 리액트 프로젝트의 프레임워크이다. Create React App처럼 리액트 프로젝트를 설정하는 기능, 라우팅 시스템, 최적화, 다국어 시스템 지원, 서버 사이드 렌더링 등 다양한 기능을 제공한다. 이 프레임워크의 라우팅 시스템은 파일 경로 기반으로 작동한다. 리액트 라우터의 대안으로 많이 사용되고 있다.

라우팅 관련 기능은 리액트 라이브러리에서 공식적으로 지원하는 것이 아니라 서드 파티로 제공되기 때문에, 이 외에도 react-location, rakkas 등의 프로젝트들이 있다.

이번에는 리액트 라우터를 사용하여 라우팅 시스템을 구축하자!🔥

  • 가장 인기 있다!!!
  • 라우팅 기능에만 집중한 라이브러리이기 때문에 리액트 프로젝트에서 라우팅 시스템 개념을 익히기에 적합!!!
  • 오랫동안 개발된 프로젝트인 만큼 다양하고 편리한 라우팅 기능을 제공하며 프로덕션에서 사용하기에 안정적

리액트 라우터를 사용하면 손쉽게 리액트 라우터로 싱글 페이지 애플리케이션(Single Page Application)을 만들 수 있다!


2. SPA(싱글 페이지 애플리케이션)이란 ???🤔

SPA는 Single Page Application의 약어로, 말 그대로 한 개의 페이지로 이루어진 애플리케이션을 의미한다. 리액트 라우터를 사용하여 여러 페이지로 구성된 프로젝트를 만들 수 있다고 했는데 왜?? 싱글 페이지 애플리케이션이라고 불리는지 의문이 든다??

기존에 사용되던 멀티 페이지는 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아 오고, 페이지를 로딩할 때마다 서버에서 CSS, JS, 이미지 파일 등의 리소스를 전달받아 브라우저 화면에 보여주었다. 각 페이지마다 다른 html 파일을 만들어서 제공을 하거나, 데이터에 따라 유동적인 html을 생성해 주는 템플릿 엔진을 사용하기도 했다. 사용자 인터랙션이 별로 없는 정적인 페이지에서는 이러한 방식이 적합하지만, 사용자 인터랙션이 많고 다양한 정보를 제공하는 모던 웹 애플리케이션에서는 적합하지 않다.

SPA의 경우 html을 한 번만 받아와서 웹 애플리케이션을 실행시킨 후, 그 이후에는 필요한 데이터만 받아와서 화면에 업데이트 해준다. 기술적으로는 한 페이지만 존재하는 것이지만, 사용자가 경험하기에는 여러 페이지가 존재하는 것처럼 느껴질 수 있다. 리액트 라우터와 같은 라우팅 시스템 통해 사용자 브라우저 주소창의 경로에 따라 알맞는 페이지를 보여지게 되는데, 이때 링크를 눌러서 다른 페이지로 이동할 때 서버에 다른 페이지의 html을 새로 요청하는 것이 아니라, 브라우저의 History API를 사용하여 브라우저 주소창의 값만 변경하고 기존에 페이지에 띄웠던 웹 애플리케이션은 그대로 유지하면서 라우팅 설정에 따라 또다른 페이지를 보여주게 된다.


3. 리액트 라우터 적용 및 기본 사용법

3.1 리액트 라우터 라이브러리 설치!

$ npm install react-router-dom --save
$ yarn add react-router-dom

3.2 프로젝트에 라우터 적용

프로젝트에 리액트 라우터를 적용할 때는 src/index.js 파일에서 react-router-dom에 내장되어 있는 BrowserRouter 컴포넌트를 사용하여 컴포넌트를 감싸준다. 이 컴포넌트는 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경하고, 현재 주소 경로에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 해준다.

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
imprt { BrowserRouter } from 'react-router-dom';


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

3.3 페이지 컴포넌트 만들기

사용자가 웹 사이트에 들어왔을 때 가장 먼저 보여주게 될 Home 페이지 컴포넌트와 웹 사이트를 소개하는 About 페이지 컴포넌트를 만들어보자!

// src/pages/Home.js
const Home = () => {
    return (
        <div>
            <h1></h1>
            <p>가장 먼저 보여지는 페이지입니다.</p>
        </div>
    );
};
export default Home;
// src/pages/About.js
const About = () => {
    return (
        <div>
            <h1>소개</h1>
            <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
        </div>
    );
};
export default About;

3.4 Route 컴포넌트로 특정 경로에 원하는 컴포넌트 보여주기

사용자의 브라우저 주소 경로에 따라 우리가 원하는 컴포넌트를 보여주기 위해 Route 라는 컴포넌트를 통해 라우트를 설정해준다. Route 컴포넌트에 어떤 경로에 어떤 컴포넌트를 보여줄지 정의해주면 경로에 따라 다른 컴포넌트를 보여줄 수 있다.

<Route path="주소 규칙" element={컴포넌트} />

그리고 Route 컴포넌트는 Routes 컴포넌트 내부에서 사용되어야 한다.

// src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";

const App = () => {
  return (
  <Routes>
    <Route path="/" element={<Home/>}/>
    <Route path="/about" element={<About/>}/>
  </Routes>
  );
};
export default App;

Link 컴포넌트는 클릭하면 다른 주소로 이동시켜주는 컴포넌트이다. 일반 웹 애플리케이션에서는 a 태그를 사용하여 페이지를 전환하는데, 리액트 라우터를 사용할 때는 해당 태그를 직접 사용하면 안 된다. 이 태그는 페이지를 전환하는 과정에서 페이지를 새로 불러오기 때문에 애플리케이션이 가지고 있던 상태들을 모두 날려 버리게 된다. 렌더링된 컴포넌트들이 모두 사라지고 다시 처음부터 렌더링하게 되는 것이다.
Link 컴포넌트를 사용하여 페이지를 전환하면 페이지를 새로 불러오지 않고 애플리케이션은 그대로 유지한 상태에서 HTML5 History API를 사용하여 페이지의 주소만 변경해준다.

<Link to="주소">링크 이름</Link>

Home 페이지에서 About 페이지로 이동할 수 있도록 Link 컴포넌트를 Home 페이지 컴포넌트에서 사용해보자!

// src/pages/Home.js
import { Link } from "react-router-dom";

const Home = () => {
    return (
        <div>
            <h1></h1>
            <p>가장 먼저 보여지는 페이지입니다.</p>
            <Link to="/about">소개</Link>
        </div>
    );
};
export default Home;

브라우저에서 방금 만든 소개 링크를 눌러보자! About 페이지가 나타난다 !!!!! 👍


4. URL 파라미터와 쿼리스트링

페이지 주소를 정의할 때 유동적인 값을 전달해야 할 때도 있다. 이는 파라미터와 쿼리로 나눌 수 있다.

  • URL 파라미터 : 특정 아이디 혹은 이름을 사용하여 특정 데이터를 조회할 때 사용
    ex) /profile/velopert
  • 쿼리스트링 : 키워드를 검색, 페이지네이션, 정렬 방식 등 데이터 조회에 필요한 옵션을 전달할 때
    ex) /articles?page=1&keyword=react

URL 파라미터는 주소의 경로에 유동적인 값을 넣는 형태고, 쿼리스트링은 주소의 뒷부분에 ?문자열 이후에 key=value로 값을 정의하면서 &로 구분하는 형태

4.1 URL 파라미터

// src/pages/Profile.js
import { useParams } from "react-router-dom";

const data = {
    velopert: {
        name: '김민준',
        description: '리액트를 좋아하는 개발자'
    },
    gildong: {
        name: '홍길동',
        description: '고전 소설 홍길동전의 주인공'
    }
};

const Profile = () => {
    const params = useParams();
    const profile = data[params.username]

    return (
        <div>
            <h1>사용자 프로필</h1>
            {profile ? (
                <div>
                    <h2>{profile.name}</h2>
                    <p>{profile.description}</p>
                </div>
            ) : (
                <p>존재하지 않는 프로필입니다.</p>
            )}
        </div>
    );
};

export default Profile;

URL 파라미터는 useParams라는 Hook을 사용하여 객체 형태로 조회할 수 있다. URL 파라미터의 이름은 라우트 설정을 할 때 Route 컴포넌트의 path props를 통해 설정한다.

위 코드에서는 data 객체에 예시 프로필 정보들을 key=value 형태로 담아주었다. 그리고 Profile 컴포넌트에서는 username URL 파라미터를 통하여 프로필을 조회한 뒤에 프로필이 존재하지 않으면 '존재하지 않는 프로필입니다.'라는 문구를 보여주고 존재한다면 프로필 정보를 보여주도록 로직을 작성했다.

App 컴포넌트에 새로운 라우트를 설정해 주자!!

// src/pages/Home.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

const App = () => {
  return (
  <Routes>
    <Route path="/" element={<Home/>}/>
    <Route path="/about" element={<About/>}/>
    <Route path="/profiles/:username" element={<Profile/>}/>
  </Routes>
  );
};
export default App;

URL 파라미터는 /profiles/:username과 같이 경로에 :를 사용하여 설정한다. 만약 URL 파라미터가 여러 개인 경우에는 /profiles/:username/:field와 같은 형태로 설정할 수 있다.

// src/pages/Home.js
import { Link } from "react-router-dom";

const Home = () => {
    return (
        <div>
            <h1></h1>
            <p>가장 먼저 보여지는 페이지입니다.</p>
            <ul>
                <li>
                    <Link to="/About">소개</Link>
                </li>
                <li>
                    <Link to="/profiles/velopert">velopert의 프로필</Link>
                </li>
                <li>
                    <Link to="/profiles/gildong">gildong의 프로필</Link>
                </li>
                <li>
                    <Link to="/profiles/void">존재하지 않는 프로필</Link>
                </li>
            </ul>
        </div>
    );
};

export default Home;

URL 파라미터에 따라 다른 결과물이 잘 보인다!!

4.2 쿼리스트링

쿼리스트링을 사용할 때는 URL 파라미터와 달리 Route 컴포넌트를 사용할 때 별도로 설정해야 하는 것이 없다.

// src/pages/About.js
import { useLocation } from "react-router-dom";

const About = () => {
    const location = useLocation();

    return (
        <div>
            <h1>소개</h1>
            <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
            <p>쿼리스트링: {location.search}</p>
        </div>
    );
};
export default About;

여기서 useLocation 이라는 Hook은 location 객체를 반환하여 현재 사용자가 보고 있는 페이지의 정보를 제공해준다. 객체에는 다음과 같은 값들이 있다.

  • pathname : 현재 주소의 경로 (쿼리스트링 제외)

  • search : 맨 앞의 ? 문자를 포함한 쿼리스트링 값

  • hash : 주소의 # 문자열 뒤의 값 (주로 History API가 지원되지 않는 구형 브라우저에서 클라이언트 라우팅을 사용할 때 쓰는 해시 라우터에 사용된다.)

  • state : 페이지로 이동할 때 임의로 넣을 수 있는 상태값

  • key : location 객체의 고유값으로 초기에는 default이며 페이지가 변경될 때마다 고유의 값이 생성된다.

http://localhost:3000/about?detail=true&mode=1 라는 주소에서 현재 쿼리스트링 값은 ?detail=true&mode=1 이 된다. 이 문자열에서 ?를 지우고, & 문자로 분리한 뒤 key와 value를 파싱하는 작업을 해야 하는데, useSearchParams 라는 Hook을 통해 간편하게 할 수 있다.

useSerachParam는 배열 타입의 값을 반환하며, 첫 번째 원소는 쿼리파라미터를 조회하거나 수정하는 메서드들이 담긴 객체를 반환한다. get 메서드를 통해 특정 쿼리파라미터를 조회할 수 있고, set 메서드를 통해 특정 쿼리파라미터를 업데이트할 수 있다. 만약 조회시에 쿼리파라미터가 존재하지 않는다면 null로 조회된다. 두 번째 원소는 쿼리파라미터를 객체 형태로 업데이트 할 수 있는 함수를 반환한다.

쿼리파라미터를 사용할 때 주의할 점은 쿼리파라미터를 조회할 때 값이 무조건 문자열 타입이어야 한다는 것이다. 즉 true 또는 false 값을 넣게 된다면 값을 비교할 때 반드시 'true'와 같이 따옴표로 감싸서 비교를 해야 하고, 숫자를 다루게 될 때는 parseInt를 사용하여 숫자 타입으로 변환을 해야 한다.

// src/pages/About.js
import { useSearchParams } from "react-router-dom";

const About = () => {
    const [searchParams, setSearchParams] = useSearchParams();
    const detail = searchParams.get('detail');
    const mode = searchParams.get('mode');

    const onToggleDetail = () => {
        setSearchParams({mode, detail: detail === 'true' ? false : true});
    };

    const onIncreaseMode = () => {
        const nextMode = mode === null ? 1 : parseInt(mode) +1;
        setSearchParams({mode:nextMode, detail});
    }
    
    return (
        <div>
            <h1>소개</h1>
            <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
            <p>mode: {mode}</p>
            <button onClick={onToggleDetail}>Toggle detail</button>
            <button onClick={onIncreaseMode}>mode + 1</button>
        </div>
    );
};
export default About;


5. 중첩된 라우트

중첩된 라우트를 이해하기 위해, 게시글 목록을 보여주는 페이지와 게시글을 읽는 페이지를 만들어보자!!

// src/pages/Articles.js
import { Link } from "react-router-dom";

const Articles = () => {
    return (
      <ul>
        <li>
            <Link to="/articles/1">게시글 1</Link>
        </li>
        <li>
            <Link to="/articles/2">게시글 2</Link>
        </li>
        <li>
            <Link to="/articles/3">게시글 3</Link>
        </li>
      </ul>
    );
};

export default Articles;
// src/pages/Article.js
import { useParams } from "react-router-dom";


const Article = () => {
    const {id} = useParams();
    return (
        <div>
            <h2>게시글 {id}</h2>
        </div>
    );
};

export default Article;
// src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Article from "./pages/Article";
import Articles from "./pages/Articles";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

const App = () => {
  return (
  <Routes>
    <Route path="/" element={<Home/>}/>
    <Route path="/about" element={<About/>}/>
    <Route path="/profiles/:username" element={<Profile/>}/>
    <Route path="/articles" element={<Articles/>}/>
    <Route path="/articles/:id" element={<Article/>}/>
  </Routes>
  );
};
export default App;
// src/pages/Home.js
import { Link } from "react-router-dom";

const Home = () => {
    return (
        <div>
            <h1></h1>
            <p>가장 먼저 보여지는 페이지입니다.</p>
            <ul>
                <li>
                    <Link to="/About">소개</Link>
                </li>
                <li>
                    <Link to="/profiles/velopert">velopert의 프로필</Link>
                </li>
                <li>
                    <Link to="/profiles/gildong">gildong의 프로필</Link>
                </li>
                <li>
                    <Link to="/profiles/void">존재하지 않는 프로필</Link>
                </li>
                <li>
                    <Link to="/articles">게시글 목록</Link>
                </li>
            </ul>
        </div>
    );
};

export default Home;

만약에 게시글 목록 페이지에서 게시글을 열었을 때, 게시글 하단에 목록을 보여줘야 한다면 아마도!!! ArticleList 컴포넌트를 따로 만들어서 각 페이지 컴포넌트에서 사용했을 것!!!

<div>
	<h2>게시글 {id}</h2>
    <ArticleList/>
</div>

그러나 중첩된 라우트를 사용한다면 좀 더 나은 방식으로 구현할 수 있다.

// src/App.js
 <Route path="/articles" element={<Articles/>}>
      <Route path=":id" element={<Article/>}/>
    </Route>

중첩된 라우트와 Outlet 컴포넌트를 사용하면 페이지끼리 공톡적으로 보여줘야 하는 레이아웃이 있을 때 유용하게 사용할 수 있다.

Articles 컴포넌트에서 리액트 라우터에서 제공하는 Outlet 컴포넌트를 사용해준다. Outlet 컴포넌트는 Route의 cildren으로 들어가는 JSX 엘리먼트를 보여주는 역할을 한다.

// src/pages/Articles.js
import { Link, Outlet } from "react-router-dom";

const Articles = () => {
    return (
    <div>
        <Outlet/>
        <ul>
            <li>
                <Link to="/articles/1">게시글 1</Link>
            </li>
            <li>
                <Link to="/articles/2">게시글 2</Link>
            </li>
            <li>
                <Link to="/articles/3">게시글 3</Link>
            </li>
        </ul>
    </div>
    );
};

export default Articles;

5.1 공동 레이아웃 컴포넌트

중첩된 라우트와 Outlet은 페이지끼리 공통적으로 보여줘야 하는 레이아웃이 있을 때도 사용가능하다.

만약 Home,About,Profile 페이지 상단에 헤더를 보여줘야 하는 상황이면 가장 먼저 Header 컴포넌트를 따로 만들어두고 각 페이지 컴포넌트에서 재사용하는 방법을 생각을 할 것 같다!! 하지만 위에서 해본 중첩된 라우트와 Outlet을 활용하여 구현할 수도 있다. 중첩된 라우트를 사용하면 컴포넌트를 한번만 사용해도 된다는 장점이 있다.

// src/Layout.js
import { Outlet } from "react-router-dom";

const Layout = () => {
    return (
        <div>
            <header style={{background: 'lightgray', padding: 16, fontSize:24}}>
                header
            </header>
            <main>
                <Outlet/>
            </main>
        </div>
    );
};

export default Layout;
// src/App.js
<Route element={<Layout/>}>
      <Route path="/" element={<Home/>}/>
      <Route path="/about" element={<About/>}/>
      <Route path="/profiles/:username" element={<Profile/>}/>
    </Route>

5.2 index props

Route 컴포넌트에는 index라는 props가 있다. 이 props는 path="/"와 동일한 의미를 가진다.

// src/App.js
  <Route path="/"element={<Layout/>}>
      <Route index element={<Home/>}/>
      <Route path="/about" element={<About/>}/>
      <Route path="/profiles/:username" element={<Profile/>}/>
    </Route>

6. 리액트 라우터 부가 기능

6.1 useNavigate

useNavigate는 Link 컴포넌트를 사용하지 않고 다른 페이지로 이동해야 하는 상황에 사용하는 Hook이다.

// src/Layout.js
import { Outlet, useNavigate } from "react-router-dom";

const Layout = () => {
    const navigate = useNavigate();

    const goBack = () => {
        // 이전 페이지로 이동
        navigate(-1);
    };

    const goArticles = () => {
        // articles 경로로 이동
        navigate('/articles');
    };

    return (
        <div>
            <header style={{background: 'lightgray', padding: 16, fontSize:24}}>
                <button onClick={goBack}>뒤로가기</button>
                <button onClick={goArticles}>게시글 목록</button>
            </header>
            <main>
                <Outlet/>
            </main>
        </div>
    );
};

export default Layout;

navigate 함수를 사용할 때 파라미터를 숫자 타입으로 주면 페이지를 앞으로 가거나 뒤로 갈 수 있다. 예를 들어서 navigate(-1)을 하면 한 번 뒤로 가고, navigate(-2)를 하면 두 번 뒤로 간다. 반대로 navigate(1)을 하면 앞으로 한 번 간다. 물론 뒤로가기를 한 번 한 상태여야 한다.

다른 페이지로 이동할 때 replace 라는 옵션을 설정해주면 해당 페이지를 페이지 기록에 남기지 않는다. 예를 들어 Home 페이지에서 About 페이지로 이동한 다음, 게시글 페이지로 이동해서 뒤로가기 버튼을 눌렀을 때, navigate('/articles', { replace : true }) 가 설정되어 있지 않다면 직전 페이지인 About 페이지가 나타나지만 이 옵션이 활성화되어 있다면 그 전의 페이지인 Home 페이지가 나타나게 된다.

// src/Layout.js
const goArticles = () => {
        // articles 경로로 이동
        navigate('/articles', {replace: true});
    };

NavLink 컴포넌트는 링크에서 사용하는 경로가 현재 라우트의 경로와 일치하는 경우 특정 스타일 또는 CSS 클래스를 적용하는 컴포넌트이다.

이 컴포넌트의 style과 className은 {isActive:boolean}을 파라미터로 전달받는 함수 타입의 값을 전달한다.

// src/pages/Articles.js
import { NavLink, Outlet } from "react-router-dom";

const Articles = () => {
    const activeStyle = {
        color: 'green',
        fontSize: 21
    };

    return (
    <div>
        <Outlet/>
        <ul>
            <li>
                <NavLink to="/articles/1"
                style={({isActive}) => (isActive ? activeStyle : undefined)}
                >게시글 1</NavLink>
            </li>
            <li>
                <NavLink to="/articles/2"
                style={({isActive}) => (isActive ? activeStyle : undefined)}
                >게시글 2</NavLink>
            </li>
            <li>
                <NavLink to="/articles/3"
                style={({isActive}) => (isActive ? activeStyle : undefined)}
                >게시글 3</NavLink>
            </li>
        </ul>
    </div>
    );
};

export default Articles;

만약 나중에 비슷한 작업을 하게 된다면 현재 NavLink를 감싼 또 다른 컴포넌트를 만들어서 다음과 같이 리팩터링하여 사용하는 것을 권장!!!👍

// src/pages/Articles.js
import { NavLink, Outlet } from "react-router-dom";

const Articles = () => {
    return (
        <div>
            <Outlet/>
            <ul>
                <ArticlesItem id={1}/>
                <ArticlesItem id={2}/>
                <ArticlesItem id={3}/>
            </ul>
        </div>
    );
};

const ArticlesItem = ({id}) => {
    const activeStyle = {
        color: 'green',
        fontSize: 21
    };

    return (  
        <li>
            <NavLink 
            to={`/articles/${id}`}
            style={({isActive}) => (isActive ? activeStyle : undefined)}
            >게시글 {id}
            </NavLink>
        </li>
    );
};

export default Articles;

6.3 NotFound 페이지 만들기

사전에 정의되지 않은 경로에 사용자가 진입했을 때, 즉 페이지를 찾을 수 없을 때 나타날 페이지이다.

// src/pages/NotFound.js
const NotFound = () => {
    return (
        <div style={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            fontSize: 64,
            position: 'absolute',
            width: '100%',
            height: '100%'
        }}>
           404 
        </div>
    );
};

export default NotFound;
// src/App.js
import { Route, Routes } from "react-router-dom";
import Layout from "./Layout";
import About from "./pages/About";
import Article from "./pages/Article";
import Articles from "./pages/Articles";
import Home from "./pages/Home";
import NotFound from "./pages/NotFound";
import Profile from "./pages/Profile";

const App = () => {
  return (
  <Routes>
    <Route path="/"element={<Layout/>}>
      <Route index element={<Home/>}/>
      <Route path="/about" element={<About/>}/>
      <Route path="/profiles/:username" element={<Profile/>}/>
    </Route>
    <Route path="/articles" element={<Articles/>}>
      <Route path=":id" element={<Article/>}/>
    </Route>
    <Route path="*" element={<NotFound/>}/>
  </Routes>
  );
};
export default App;

여기서 *는 wildcard 문자이다. 아무 텍스트나 매칭한다는 뜻이다. 이 라우트 엘리먼트의 상단에 위치하는 라우트들의 규칙을 모두 확인하고, 일치하는 라우트가 없으면 이 라우트가 화면에 나타난다.

6.4 Navigate 컴포넌트

Navigate 컴포넌트는 컴포넌트를 화면에 보여주는 순간 다른 페이지로 이동하고 싶을 때 사용하는 컴포넌트이다. 즉, 페이지를 리다이렉트 하고 싶을 때 사용한다. 예를 들어 사용자의 로그인이 필요한 페이지인데 로그인을 안 했다면 로그인 페이지로 바로 넘어가도록 하는 상황에서 사용할 수 있다.

// src/pages/Login.js
const Login = () => {
    return (
        <div>로그인 페이지</div>
    );
};

export default Login;
// src/pages/Mypage.js
import { Navigate } from "react-router-dom";

const MyPage = () => {
    const isLoggedIn = false;

    if (!isLoggedIn) {
        return <Navigate to ="/login" replace={true} />;
    }


    return <div>마이 페이지</div>;
};

export default MyPage;

여기서 isLoggedIn은 현재 false라는 고정값을 가지고 있지만, 이 값이 로그인 상태에 따라 true 또는 false를 가리킨다고 가정해보자.

위 컴포넌트에서는 만약 이 값이 false라면 Navigate 컴포넌트를 통해 /login 경로로 이동한다. 여기서 replace props는 useNavigate에서 설명한 것과 동일하다. 페이지를 이동할 때 현재 페이지를 기록에 남기지 않기 때문에 이동 후 뒤로가기를 눌렀을 때 두 페이지 전의 페이지로 이동한다.

// src/App.js

import { Route, Routes } from "react-router-dom";
import Layout from "./Layout";
import About from "./pages/About";
import Article from "./pages/Article";
import Articles from "./pages/Articles";
import Home from "./pages/Home";
import Login from "./pages/Login";
import MyPage from "./pages/MyPage";
import NotFound from "./pages/NotFound";
import Profile from "./pages/Profile";

const App = () => {
  return (
  <Routes>
    <Route path="/"element={<Layout/>}>
      <Route index element={<Home/>}/>
      <Route path="/about" element={<About/>}/>
      <Route path="/profiles/:username" element={<Profile/>}/>
    </Route>
    <Route path="/articles" element={<Articles/>}>
      <Route path=":id" element={<Article/>}/>
    </Route>
    <Route path="/login" element={<Login/>}/>
    <Route path="/mypage" element={<MyPage/>}/>
    <Route path="*" element={<NotFound/>}/>
  </Routes>
  );
};
export default App;

브라우저 주소창에 /mypage 경로를 직접 입력해서 들어가보면 페이지가 로딩되는 순간 바로 Login 페이지로 이동한다.

이번 장에서는 리액트 라우터를 사용하여 주소 경로에 따라 다양한 페이지를 보여 주는 방법을 알아봤다. 지금 해커톤을 준비하고 있어서 많은 도움이 되었다!!! 해커톤도 파이팅!!!! 🔥🔥🔥🔥🔥

참고자료

리액트를 다루는 기술 - 김민준
https://amor-fati.tistory.com/105

profile
It's better to be a pirate than join the navy ☠️

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기