React

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

킹우현 2023. 2. 13. 23:17

 

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