본문 바로가기
React ⚛️

[React] Routing의 개념과 React Router에 대해 알아보자

by 킹우현 2023. 2. 13.

 

React Router를 사용하면 새로운 페이지를 로드하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가지기 때문에 불필요한 렌더링을 막을수 있다.

 

1) 라우팅(Routing)이란 ?

웹을 사용할 때 전통적인 링크 연결방식은 HTML에서 <a> 태그를 사용하여 href 속성에 연결할 링크를 넣어주는 방식입니다.

 

이러한 방식은 웹사이트의 규모가 크지 않을 때는 사용하는데 크게 불편함이 없지만 로드되는 컨텐츠나 페이지의 용량자체가 크다면 불편함을 초래할 수 있습니다.

 

애초에 링크로 연결되는 방식은 각각의 HTML 파일을 로드하는 것이기 때문에 새로운 페이지로 이동할 때마다 새로고침이 발생할 것이며 해당 페이지 자체 또는 로드할 컨텐츠의 용량이 크다면 사용자 입장에서는 불만이 생길 수 밖에 없을 것입니다.

(페이스북이나 인스타그램처럼 퓨어 텍스트보다 압도적으로 높은 용량의 이미지/영상 컨텐츠가 주를 이루는 페이지일수록 더 심해짐)

 

그래서 SPA(Single Page Application)이라는 수단이 도입되었으며, 이는 페이지를 로드하면서 페이지 내부의 모든 구성요소를 렌더링 하는 것이 아니라 페이지를 이동하면서 바뀌는 부분만 렌더링 하는 것입니다.

 

먼저 SPA라 하더라도 한 개의 페이지만 사용하는 것은 아닙니다. Header, Navigator, Footer 처럼 중복되는 컴포넌트를 제외하더라도 사용자 정보, 컨텐츠 정보, 컨텐츠 세부정보 등의 컴포넌트들의 페이지 주소를 다르게 구성해야 할 필요가 있습니다.

 

주소에 따라 서로 다른 컴포넌트들의 배치를 변경하는 작업라우팅(Rounting)이라고 합니다. 즉, 경로(주소)에 따라서 컴포넌트를 변경하는 과정에서 데이터가 출발점에서 도착점 까지 도착할 수 있는 경로들을 구성하는 작업을 의미합니다.

 

React에서는 자체적으로 Router 기능이 포함되어 있지 않습니다. 개발자가 주소별로 다른 컴포넌트를 Display 해야 하는 번거로움이 있습니다.

👉🏻 React SPA Router를 위해 가장 많이 사용하는 외부 모듈이 바로 React Router !

 

2) React Router 설치

// React Router Install
$ npm install react-router-dom

// 특정 버전 React-Router Install
$ npm install react-router-dom@6.3.0

ReactRouter를 사용하기 위해서는 먼저 npm을 이용해 설치를 해줘야 합니다.

 

그리고 react-router-dom 모듈 안에 있는 <Link /> 모듈과 <BrowserRouter />, <Routes />, <Route /> 모듈을 사용해서 각각을 연결해줍니다.

 

여기에서 Link 태그는 기존의 a 태그 역할을 할 것이며, BrowserRouter, Routes, Route는 Link 태그에 부여된 to 속성의 값을 따라 각각 다른 컴포넌트를 보여주게 됩니다.

 

3) React Router 주요 컴포넌트

🚨 react-router-dom v6 에서는 더이상 Switch 모듈을 사용하지 않습니다. 대신 Routes 모듈을 사용합니다.

 

React Router는 크게 3가지 기능을 담당합니다. 라우팅 기능 경로 매칭 기능 그리고 경로 변경 기능을 내장하고 있습니다. 

<Router>
	<Link/>
	<Link/>
	<Route />
	<Route />
</Router>

<Router> : <Route>와 <Link>컴포넌트가 함께 유기적으로 동작하도록 묶어주는데 사용합니다. <Route>와 <Link> 컴포넌트는 DOM 트리 상에서 항상 <Router>를 공통 상위 컴포넌트로 가져야합니다.(위 예시에서는 BrowserRouter 사용)

 

<Route path="/about" element={<About/>}/>

<Route><Route> : 현재 주소창의 경로와 매치될 경우에 보여줄 컴포넌트를 지정하는데 사용됩니다. path prop을 통해서 매치시킬 경로를 지정하고 element prop을 통해서 매치되었을 때 보여줄 컴포넌트를 할당합니다.

 

<Routes>
  <Route exact paht="/" element={< Home/>}></Route>
  <Route paht="/product1" element={< Product1/>}></Route>
  <Route paht="/product2" element={< Product2/>}></Route>
  <Route path="/" element={'Not found'}></Route>
</Routes>

v6으로 업데이트 되면서 <Route> 태그들을 <Routes> 태그로 감싸주어야 합니다.

 

<Link to="/about">About</Link>

<Link> : html의 <a> 태그와 유사한 기능, to prop을 통해서 이동할 경로를 지정해줍니다. 기존 HTML의 <a>태그가 새로고침을 통해 처음부터 렌더링을 수행한다면 <Link> 컴포넌트는 페이지 전환을 방지하는 기능을 내장하고 있습니다. 즉 새로고침을 하지 않더라도 해당 페이지의 소스를 렌더링 하게 됩니다. 

 

4) 실습 및 구현

import { Link, Route, BrowserRouter as Router } from 'react-router-dom'

먼저 React Router 컴포넌트를 사용하기 위해서는 react-router-dom에서 import 해주면 됩니다. 

 

<header>
        <Link to="/">
          <button>Home</button>
        </Link>
        <Link to="/about">
          <button>about</button>         
        </Link>
        <Link to="/users">
         <button>User</button>
        </Link>
</header>

Header 부분을 <Link> 컴포넌트를 사용해서 리펙토링 합니다. to prop에 해당 메뉴 클릭 시 이동해야 할 경로를 지정합니다.

 

<main>
        <Route exact path = "/" element={<Home/>} />
        <Route path="/about" element={<About/>} />
        <Route path="/users" element={<NotFound/>} />
</main>

main 부분은 <Route> 컴포넌트를 사용합니다. path prop에 매치 할 때 비교될 경로를 지정하고, element prop에 매치할 때 보여줄 컴포넌트를 할당합니다.

 

여기서 <Route> 컴포넌트에만 exact prop이 사용된 이유는 React Router의 디폴트 매칭 규칙 때문입니다.

 

React Router는 path prop의 경로와 현재 브라우저 주소창의 url 경로(location.pathname)를 비교합니다. 그리고 현재 url 경로 값이 <Route>의 path prop 값과 앞부분만 일치해도 같은것으로 간주합니다.

 

따라서 path가 / 일 경우 / 뿐만 아니라 / 로 시작하는 모든 url 경로와 매치가 되기 때문에 exact prop 이 없으면 home 컴포넌트가 url 경로와 상관없이 항상 보여지게 됩니다.

 

하지만 exact prop을 붙여주면 url 경로 값이 <Route>의 path 값과 전체가 일치해야 매치가 일어나고 처리를 해줍니다.

 

import React from 'react'
import { Link, Route, BrowserRouter as Router } from 'react-router-dom'
import Home from "./Home";
import About from "./About";
import NotFound from "./NotFound";

function App() {

  return (
    <Router>
      <header>
        <Link to="/">
          <button>Home</button>
        </Link>
        <Link to="/about">
          <button>about</button>         
        </Link>
        <Link to="/users">
         <button>User</button>
        </Link>
      </header>
      <hr/>
      <main>
        <Route exact path = "/" element={<Home/>} />
        <Route path="/about" element={<About/>} />
        <Route path="/users" element={<NotFound/>} />
      </main>
    </Router>
  );
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

마지막으로 <Router> 컴포넌트를 사용해 전체를 감싸줍니다. 위와 같이 App.js 에서 <Route>와 <Link>전체를 감싸도 되고 index.js 에서<App /> 전체를 감싸도 됩니다.

 

5) 중첩 라우팅(Nested routes) 사용법

중첩 라우팅이란 서브 페이지를 만든다고도 할 수 있는데 해당하는 페이지에서 조금 더 구체적으로 구분을 지어 화면을 교체(표시) 해줄 필요가 있을 때 사용됩니다.

 

예를 들면, 쇼핑몰 상세 페이지가 있을 것인데 'myshop/products' 라는 주소로 입력했을 때는 단순히 쇼핑몰에 게시된 상품들이 나열되어 있다고 가정해봅시다.

 

여러 상품들 중 하나의 상품을 클릭하면 해당하는 상품의 상세 페이지를 보여주고 싶을 때 중첩 라우팅을 사용할 수 있습니다.

위 예시에서 'myshop/products/01'과 같은 URL을 입력했다면 쇼핑몰 상품의 01번째 아이템 페이지가 나타나야 합니다.

<Route path="/about" element={<About />}>
  <Route path="location" element={<Location />}></Route>
</Route>

Route 안에 중첩(자식) Route를 작성해서 서브 페이지를 만들어 줄 수 있습니다.


서브 페이지의 path는 / 를 생략하고 작성하며, element는 보여줄 컴포넌트 또는 HTML 태그를 작성해주면 됩니다.

 

import { Outlet } from 'react-router-dom';

function About() {
  return (
    <div>
      <div>
        <h2>여기는 About 페이지입니다.</h2>
        <p>대충 쇼핑몰 페이지라는 뜻</p>
      </div>
      <Outlet />
    </div>
  );
}

위와 같이 react-router-dom에서 Outlet을 import하고 <Outlet/>으로 부모 라우트의 컴포넌트에서 자식 라우트 컴포넌트의 위치를 지정해주면 중첩 라우팅이 완료됩니다.

 

5-1) 중첩 라우팅 시 부모 컴포넌트에서 자식 컴포넌트에게 props를 전달하는 방법

// router.tsx
<Route path="/*" element={<Parent/>}>
    <Route path="child" element={<Child/>} />
</Route>
// 부모 컴포넌트
…
      <Outlet context={{ coinId }} />
…

부모 컴포넌트안에 <Outlet/>으로 원하는 자손 컴포넌트 위치를 정합니다. 그리고 context prop으로 자손 컴포넌트에게에게 넘기고 싶은 값을 넣습니다.

 

//자손 컴포넌트
import { useOutletContext } from 'react-router-dom';

const {coinId} = useOutletContext();

 

자손컴포넌트에서 위의<Outlet/>의 context prop을 가지려면 useOutletContext Hook을 사용해야 합니다.

//자손 컴포넌트
import { useOutletContext } from 'react-router-dom';

type ChildProps = {
    coinId: string
}

function Child() {
…
    const {coinId} = useOutletContext<ChildProps>();
…
}

타입스크립트를 사용한다면 당연히 interface를 선언한 뒤 사용해야 합니다.

 

 

 

( 출처 : https://about-tech.tistory.com/10 , https://velog.io/@goodenough/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%9D%BC%EC%9A%B0%ED%84%B0react-router https://velog.io/@reasonz/2022.07.14-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%9D%BC%EC%9A%B0%ED%84%B0-%EC%A4%91%EC%B2%A9-%EB%9D%BC%EC%9A%B0%ED%8C%85-nested-routes-outlet )

 

[2022.07.14] 리액트 라우터 - 중첩 라우팅 nested routes, outlet

리액트 라우터로 중첩 라우팅(nested routing) 하는 방법중첩 라우팅이란 서브 페이지를 만든다고도 할 수 있는데 해당하는 페이지에서 조금 더 구체적으로 구분을 지어 화면을 교체(표시) 해줄 필

velog.io

 

[React] 리액트 라우터(react-router)

URL에 따라서 그에 상응하는 화면을 전송해주는 것을 Routing이라고 한다.리액트에서 라우팅 기능을 구현하는 것은 쉽지 않지만 React Router는 리액트에서 비교적 쉽게 라우팅이 가능하도록 도와준

velog.io

 

[React] React Router 란?

How Can I Change View Regarding to URL(How to use React Router)? [Programming] SPA(Single Page Application)이란? 장점과 단점 SPA는 왜 쓰는 걸까요? SPA란 한 페이지에서 작동하는 애플리케이션을 의미합니다. 과거의 웹사

about-tech.tistory.com