조각조각 - CRA 라우팅(react-router-dom v6, Router, Routes, Switch)

eocode·2023년 3월 22일
1

리액트 조각조각

목록 보기
7/11
post-thumbnail

SPA(Single Page Application)에서 페이지를 새로고침하지 않고 페이지를 렌더링 하기 위해서 라우팅 솔루션(React Router)을 사용해야 합니다. Next.js와 다르게 CRA(Create React App)는 특정 라우팅 솔루션을 규정하지 않습니다. 가장 인기 있는 라우팅 솔루션은 React Router입니다. 이 때 Router 컴포넌트는 브라우저의 URL을 읽어들이고, 해당 URL에 맞는 컴포넌트를 렌더링하는 역할을 수행합니다.

Next.js의 경우 src/pages 폴더 내 페이지 파일을 생성하면 자동으로 라우팅이 구현됩니다.

CRA 라우팅 구현 과정

1. react-router-dom 설치

npm i react-router-dom

2. React Router import

React Router를 사용할 컴포넌트에서 import합니다. CRA로 프로젝트를 생성하였기 때문에 src/app.tsx에 import합니다.

import { BrowserRouter as Router, Route, Switch } from ‘react-router-dom’;

3. 페이지 컴포넌트 생성

import React from "react";

const Start = () => {
  return <>시작페이지 입니다.</>;
};

export default Start;

4. 라우팅 설정 코드 작성

React Router를 import한 컴포넌트에 라우팅 설정 코드를 작성합니다.
이 과정에서 이전에 생성한 페이지 컴포넌트와 URL 정보가 연결됩니다.

//BrowserRouter 사용 라우팅 예제 코드

import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

//Pages
import Start from "./pages/Start";
import Main from "./pages/Main";

//pathes
const path = {
  start: "/",
  main: "/main"
};

function App() {
  return (
    <Router> // BrowserRouter
      <Routes>
        <Route path={path.start} element={<Start />} />
    	<Route path={path.main} element={<Main />} />
      </Routes>
    </Router>
  );
}

export default App;

🚨 react-router-dom 버전 업데이트 (v5.0 -> v6.0)

react-router-dom이 6.0 버전으로 업데이트 되면서 많은 변경사항이 발생하였습니다.

1. component -> element

//v5.0
<Route path="/" component={HomePage}/>
//v6.0
<Route path="/" element={<HomePage />} />

2. switch -> routes

//v5.0
<BrowserRouter>
	<Switch>
        <Route path={path.start} element={<Start />} />
    	<Route path={path.main} element={<Main />} />
	</Switch>
</BrowserRouter>
//v6.0
<BrowserRouter>
	<Routes>
        <Route path={path.start} element={<Start />} />
    	<Route path={path.main} element={<Main />} />
	</Routes>
</BrowserRouter>

3. exact 옵션 삭제

v5.0

  • 일부 일치 하위 url 매칭 처리가 기본
  • url 정확한 일치 처리 위해 exact 옵션 사용

v6.0

  • 정확한 일치 처리를 위한 exact 옵션이 기본으로 적용되어 옵션 삭제
  • 하위 url 처리하기 위해 /* 사용

⭐️ 자세한 예시 코드는 아래 "Switch, Routes 왜 사용할까?"에서 정리하였습니다.

4. 중첩 라우트와 자손 라우트 사용법

5. useRoutes 훅

6. useHistory 훅 -> useNavigate 훅

4, 5, 6 변경사항은 게시글을 따로 분리해서 정리하였습니다.
🔗 조각조각 - CRA 라우팅(중첩 라우트와 자손 라우트, useRoutes, useNavigate)

다른 타입의 Router 컴포넌트

위 예제 코드는 BrowserRouter를 사용한 경우 입니다. Router 컴포넌트는 BrowserRouter 외에도 HashRouter, MemoryRouter, NativeRouter, StaticRouter가 존재합니다.

  • BrowserRouter : HTML5의 History API를 사용하여 URL을 관리합니다.
  • HashRouter : URL의 해시값을 사용하여 URL을 관리합니다.
  • MemoryRouter : 메모리에서 URL을 관리합니다.
  • NativeRouter : React Native에서 사용합니다.
  • StaticRouter : 서버사이드 렌더링에서 사용합니다.

Routes(Switch) 왜 사용할까?

exact 옵션이 의미

우선 Route 컴포넌트에서 exact 옵션이 의미하는 것이 무엇인지 알아야 합니다. 간단히 말하자면 exact 옵션은 url이 완전히 일치하는 경우만 페이지를 렌더링 해주는 옵션입니다.

//case 1
<Route path="/" component= { Home } />
<Route path="/A" component= { A } />
<Route path="/B" component= { B } />
//case 2
<Route path="/" exact component= { Home } />
<Route path="/A" exact component= { A } />
<Route path="/B" exact component= { B } />

앞서 react-router-dom v5.0와 v6.0 차이에서 언급되었듯이 v5.0는 url이 부분적으로 일치하는 경우 모두를 렌더링 합니다. 그렇기 때문에 case 1 코드에서 "/" url로 접근하면 Home, A, B 페이지가 모두 렌더링 됩니다. 따라서 "/" url로 접근 시 Home 페이지만 렌더링 하고 싶다면 case 2와 같이exact 옵션을 추가해주어야 합니다.

Routes(Switch)?

그렇다면 Routes(Switch)는 언제, 왜 사용해야 할까요?
📌 v6.0에서 < Switch > 대신 < Routes >를 사용합니다.

위 case 2를 자세히 살펴보면 exact 옵션 자체가 하나의 페이지만 렌더링되도록 하는게 아닙니다. 모든 route 컴포넌트에 exact 옵션이 추가되어있어 모든 route 컴포넌트가 url이 완전히 일치해야 페이지가 렌더링 됩니다. 그러다보니 결과적으로 하나의 페이지만 렌더링 됩니다.

그럼 하나의 페이지만 렌더링 하기 위해 모든 route 컴포넌트에 exact 옵션을 추가하는것이 과연 옳을까요?? 답은 아니다 입니다.

만약 사용자가 전혀 다른 url 또는 /A/* 와 같은 하위 url로 접근을 하려 할때 어떻게 동작할지를 생각해 보아야 합니다. 전혀 다른 url에 특정 페이지를 렌더링 하고 싶다고 모든 전혀 다른 url을 exact 옵션으로 추가하는것은 불가능 합니다. 또 모든 완벽히 일치하는 하위 url을 exact 옵션으로 추가하는 것도 불가능 합니다.

이때 사용되는 것이 Routes(Switch)입니다.

//case 3
<Switch>
  <Route path="/" exact component= { Home } />
  <Route path="/A" component= { A } />
  <Route path="/A/SUB" component= { A SUB } />
  <Route path="/B" component= { B } />
  <Route path="*" component= { ErrorPage } />
</Switch>

switch는 route 컴포넌트를 감싸고 있으며 사용자가 url로 접근시 switch 내부 route들을 순서대로 접근하며 매칭되는 route 하나를 렌더링합니다.
(이때 url 매칭 규칙은 v5.0, v6.0인지에 따라 다름)

case 3

  • "/" url로 접근 시 Home 페이지가 렌더링됩니다. 이때 만약 exact 옵션이 없었다면 Switch 내부 Route들을 순서대로 접근하여 매칭 여부를 확인 하기 때문에 모든 url이 <Route path="/" exact component= { Home } />에 매칭되어 Home 페이지만 렌더링 됩니다.
  • "/A" url로 접근 시 A 페이지가 렌더링됩니다. 만약 Switch로 감싸져있지 않았다면 A 페이지와 A SUB 페이지 둘다 렌더링됩니다.
  • path를 "*"로 지정하여 전혀 다른 url이 입력될 시 에러페이지가 렌더링 됩니다.

exact가 기본인 react-router-dom v6.0

<Routes>
  <Route path="/" element= { Home } />
  <Route path="/A" element= { A } />
  <Route path="/A/*" element= { A ALL SUB } />
  <Route path="/B" element= { B } />
  <Route path="*" element= { ErrorPage } />
</Routes>

react-router-dom v6.0의 경우 exact 옵션이 기본이기 때문에 path="/"에 exact 옵션을 줄 필요가 없습니다. 대신 일부만 url만 겹치는 경우, 즉 하위 url에 페이지를 렌더링 하기 위해서 path="/A/*"로 설정합니다.

  • "/A" url 요청 -> A 페이지 렌더링
  • "/A/abcd" url 요청 -> A ALL SUB 페이지 렌더링
  • "/A/test" url 요청 -> A ALL SUB 페이지 렌더링

정리하면 Routes(Switch)는 매칭되는 페이지 컴포넌트 하나만을 렌더링 하기 위함이고 exact 옵션은 url 매칭 규칙 옵션입니다.

참고자료

profile
프론트엔드 개발자

0개의 댓글