React Router

ν•™μŠ΅ ν‚€μ›Œλ“œ

  • Router

  • React Router

    • BrowserRouter

      • history API

    • Routes

    • Route

    • MemoryRouter

  • 동적 λΌμš°νŒ…

    • URL Parameter

    • useParams

    • Query String

    • useSearchParams

  • 컴퓨터 λ„€νŠΈμ›Œν¬ 간에 데이터 νŒ¨ν‚·μ„ μ „μ†‘ν•˜λŠ” λ„€νŠΈμ›Œν¬ μž₯μΉ˜λ‹€.

  • 즉, μ„œλ‘œ λ‹€λ₯Έ λ„€νŠΈμ›Œν¬ 간에 졜적의 경둜λ₯Ό μ°Ύμ•„λ‚΄λŠ” μ•Œκ³ λ¦¬μ¦˜μ„ ν™œμš©ν•΄ 쀑계 역할을 ν•΄μ£ΌλŠ” μž₯μΉ˜λ‹€.

React Router

  • Reactμ—μ„œ μ£Όμ†Œ(URL)에 λ”°λ₯Έ μ»΄ν¬λ„ŒνŠΈ λ Œλ”λ§μ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ 라이브러리

  • Context APIλ₯Ό 기반으둜 ν•œ 라이브러리

πŸ€” μ™œ React Router 을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”κ°€?

μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λΌμš°νŒ…μ΄λΌλŠ” κ°œλ…μ€ μ‚¬μš©μžκ°€ μš”μ²­ν•œ URL에 따라 μ•Œλ§žλŠ” νŽ˜μ΄μ§€λ₯Ό λ³΄μ—¬μ£ΌλŠ” 것을 μ˜λ―Έν•œλ‹€. μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€λ•Œ ν”„λ‘œμ νŠΈλ₯Ό ν•˜λ‚˜μ˜ νŽ˜μ΄μ§€λ‘œ ꡬ성할 μˆ˜λ„ 있고, μ—¬λŸ¬ νŽ˜μ΄μ§€λ₯Ό ꡬ성할 μˆ˜λ„ μžˆλ‹€. 예λ₯Ό λ“€μ–΄ λΈ”λ‘œκ·Έλ₯Ό λ§Œλ“ λ‹€λ©΄, ν™ˆ, 포슀트 λͺ©λ‘, 포슀트, κΈ€μ“°κΈ° λ“±μ˜ λ‹€μ–‘ν•œ νŽ˜μ΄μ§€λ“€μ΄ μžˆλ‹€. λ˜ν•œ 이 νŽ˜μ΄μ§€λ“€μ— 따라 μ£Όμ†Œ(URL)도 λ§Œλ“€μ–΄μ€˜μ•Ό ν•œλ‹€. μ£Όμ†Œκ°€ μžˆμ–΄μ•Ό, μœ μ €λ“€μ΄ λΆλ§ˆν¬λ„ ν•  수 있고 μ„œλΉ„μŠ€μ— ꡬ글을 톡해 μœ μž…λ  수 있기 λ•Œλ¬Έμ΄λ‹€. μ΄λ ‡κ²Œ μ—¬λŸ¬ νŽ˜μ΄μ§€λ‘œ κ΅¬μ„±λœ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€ λ•Œ νŽ˜μ΄μ§€λ³„λ‘œ μ»΄ν¬λ„ŒνŠΈλ“€μ„ λΆ„λ¦¬ν•΄κ°€λ©΄μ„œ ν”„λ‘œμ νŠΈλ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ 것이 λ°”λ‘œ λΌμš°νŒ… μ‹œμŠ€ν…œ(React Router)이닀.

πŸ€– React Router 의 μ—­ν™œ

μ‚¬μš©μžμ˜ λΈŒλΌμš°μ € μ£Όμ†Œμ°½μ˜ κ²½λ‘œμ— 따라 μ•Œλ§žλŠ” νŽ˜μ΄μ§€λ₯Ό 보여쀀닀. 이후 링크λ₯Ό λˆŒλŸ¬μ„œ λ‹€λ₯Έ νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•˜κ²Œ 될 λ•Œ μ„œλ²„μ— λ‹€λ₯Έ νŽ˜μ΄μ§€μ˜ html을 μƒˆλ‘œ μš”μ²­ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, λΈŒλΌμš°μ €μ˜ History APIλ₯Ό μ‚¬μš©ν•˜μ—¬ λΈŒλΌμš°μ €μ˜ μ£Όμ†Œμ°½μ˜ κ°’λ§Œ λ³€κ²½ν•˜κ³  기쑴에 νŽ˜μ΄μ§€μ— λ„μ› λ˜ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ·ΈλŒ€λ‘œ μœ μ§€ν•˜λ©΄μ„œ λΌμš°νŒ… 섀정에 따라 또 λ‹€λ₯Έ νŽ˜μ΄μ§€λ₯Ό λ³΄μ—¬μ£Όκ²Œ λœλ‹€.

React Router μ‚¬μš©λ²•

βš™οΈ React Router μ„€μΉ˜

npm i react-router-dom

  • HTML5의 History APIλ₯Ό μ‚¬μš©ν•˜μ—¬ νŽ˜μ΄μ§€λ₯Ό μƒˆλ‘œ λΆˆλŸ¬μ˜€μ§€ μ•Šκ³ λ„ μ£Όμ†Œλ₯Ό λ³€κ²½ν•˜κ³  ν˜„μž¬ μ£Όμ†Œμ˜ κ²½λ‘œμ— κ΄€λ ¨λœ 정보λ₯Ό λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•΄ μ£ΌλŠ” μ—­ν™œμ„ μˆ˜ν–‰ν•œλ‹€.

  • λΌμš°νŒ…μ„ 진행할 μ»΄ν¬λ„ŒνŠΈ μƒμœ„μ— BrowserRouter μ»΄ν¬λ„ŒνŠΈλ₯Ό μƒμ„±ν•˜κ³  감싸주어야 ν•œλ‹€.

πŸ“– History API

history μ „μ—­ 객체λ₯Ό 톡해 λΈŒλΌμš°μ € μ„Έμ…˜ νžˆμŠ€ν† λ¦¬μ— λŒ€ν•œ 접근을 μ œκ³΅ν•©λ‹ˆλ‹€.

λΈŒλΌμš°μ €μ—μ„œ νŽ˜μ΄μ§€ λ‘œλ”©μ„ ν•˜λ©΄, μ„Έμ…˜ νžˆμŠ€ν† λ¦¬λ₯Ό κ°–λŠ”λ‹€. λΈŒλΌμš°μ €λŠ” 이 νžˆμŠ€ν† λ¦¬λ₯Ό stack으둜 κ΄€λ¦¬ν•œλ‹€. μ„Έμ…˜ νžˆμŠ€ν† λ¦¬λŠ” νŽ˜μ΄μ§€λ₯Ό 이동할 λ•Œ λ§ˆλ‹€ μŒ“μ΄λ©°, 이λ₯Ό 톡해 λ’€λ‘œκ°€κΈ° λ˜λŠ” μ•žμœΌλ‘œ κ°€κΈ° 같은 이동이 κ°€λŠ₯ν•˜λ‹€.

β‡’ "μ–΄λ–€ νŽ˜μ΄μ§€λ₯Ό νƒμƒ‰ν–ˆλŠ”μ§€μ— λŒ€ν•΄μ„œ historyλ₯Ό μŒ“λŠ” 것" 이라고 μƒκ°ν•˜λ©΄ λœλ‹€.

πŸ€” μ™œ History APIλ₯Ό μ‚¬μš©ν•˜κ²Œ λ˜λŠ”κ°€?

  • ReactλŠ” SPA의 κΈ°λ°˜μ΄λ‹€. νŽ˜μ΄μ§€κ°€ λ‘œλ”©μ΄ λ˜μ–΄ λ³€κ²½λ˜λŠ”κ²ƒ 처럼 λ³΄μ΄μ§€λ§Œ μ»΄ν¬λ„ŒνŠΈλ₯Ό 톡해 화면을 μ—…λ°μ΄νŠΈ(λ¦¬λ Œλ”λ§)ν•΄μ€€λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ‹€μ œλ‘œλŠ” ν™”λ©΄ 이동이 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€. 그렇기에 History APIλ₯Ό μ‚¬μš©ν•˜κ²Œ 되면 ν™”λ©΄ 이동 없이 URL을 μ—…λ°μ΄νŠΈ 해쀄 수 μžˆλ‹€.

Routes & Route

  • Routes와 RouteλŠ” React Router v6λΆ€ν„° λ„μž…λœ κ°œλ…μ΄λ‹€.

  • λͺ¨λ“  Route의 μƒμœ„ κ²½λ‘œμ— μ‘΄μž¬ν•΄μ•Ό ν•˜λ©°, location λ³€κ²½ μ‹œ ν•˜μœ„μ— μžˆλŠ” λͺ¨λ“  Routeλ₯Ό μ‘°νšŒν•΄ ν˜„μž¬ locationκ³Ό λ§žλŠ” Routeλ₯Ό μ°Ύμ•„μ€€λ‹€.

  • ν˜„μž¬ λΈŒλΌμš°μ €μ˜ location(window.location.path 정보λ₯Ό κ°€μ Έμ˜¨λ‹€)μƒνƒœμ— 따라 λ‹€λ₯Έ elementλ₯Ό λ Œλ”λ§ν•œλ‹€.

<Route path="/경둜" element={<Component />} />

  • λΈŒλΌμš°μ € ν™˜κ²½μ΄ μ•„λ‹Œ κ³³μ—μ„œ ReactRouterκ°€ ν¬ν•¨λœ μ»΄ν¬λ„ŒνŠΈλ₯Ό ν…ŒμŠ€νŠΈ ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

  • MemoryRouterλŠ” μ£Όμ†Œλ₯Ό 가지고 μžˆμ§€ μ•Šμ•„, μ£Όμ†Œλ₯Ό λ”°λ‘œ μž‘μ•„μ£Όμ–΄μ•Ό ν•œλ‹€.

<MemoryRouter initialEntries={['/경둜']} >

πŸ‘©πŸ»β€πŸ’» React Router κ°„λ‹¨ν•œ 예제

// main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';

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

import App from './App';

function main() {
  const container = document.getElementById('root');
  if (!container) {
    return;
  }

  const root = ReactDOM.createRoot(container);
  root.render(
    <React.StrictMode>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </React.StrictMode>
  );
}

main();
// App.tsx

import { Routes, Route } from 'react-router-dom';

import Homepage from './pages/HomePage';
import AboutPage from './pages/AboutPage';

import Header from './components/Header';
import Footer from './components/Footer';

export default function App() {
  return (
    <div>
      <Header />
      <main>
        <Routes>
          <Route path="/" element={<Homepage />} />
          <Route path="/about" element={<AboutPage />} />
        </Routes>
      </main>
      <Footer />
    </div>
  );
}
// App.test.tsx

import { render, screen } from '@testing-library/react';

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

import App from './App';


describe('App', () => {

  function renderApp(path: string) {
    render((
    <MemoryRouter initialEntries={[path]}> 
      <App />
    </MemoryRouter>
    ));
  }
 
  context('when the current path is β€œ/”', () => {
    it('renders the home page', () => {
    renderApp('/');

    screen.getByText(/Hello/);
    });
  });
 
  context('when the current path is β€œ/about”', () => {
    it('renders the about page', () => {
    renderApp('/about');

    screen.getByText(/About/);
    });
  });
});

동적 λΌμš°νŒ…

  • 동적 Routing은 경둜λ₯Ό 미리 정해두지 μ•Šκ³  λ™μ μœΌλ‘œ μ„€μ •ν•˜λŠ” 방식이닀.

  • 라우트의 κ²½λ‘œμ— νŠΉμ • 값을 λ„£μ–΄ ν•΄λ‹Ή νŽ˜μ΄μ§€λ‘œ 이동 ν•  수 있게 ν•˜λŠ” 것

πŸ€” 동적 λΌμš°νŒ…μ΄ ν•„μš”ν•œ μ΄μœ λŠ”?

React Router λ₯Ό μ‚¬μš©ν•΄μ„œ 미리 ν”„λ‘œμ νŠΈμ— μ‚¬μš©ν•  κ²½λ‘œλ“€κ³Ό 보여쀄 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ •μ˜ν•΄λ‘”λ‹€. ν•˜μ§€λ§Œ λ³΅μž‘ν•˜κ³  규λͺ¨κ°€ 큰 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” 경둜λ₯Ό 미리 μ„€μ •ν•˜λŠ” λ°©μ‹λ§ŒμœΌλ‘œλŠ” μ²˜λ¦¬ν•˜κΈ° νž˜λ“  μž‘μ—…μ΄ μ‘΄μž¬ν•œλ‹€.

예λ₯Ό λ“€μ–΄ μ‡Όν•‘λͺ°μ—λŠ” λ‹€μ–‘ν•œ μƒν’ˆμ΄ μ‘΄μž¬ν•˜κ³ , μƒν’ˆλ¦¬μŠ€νŠΈκ°€ 있고, λ˜ν•œ μƒν’ˆ μƒμ„ΈνŽ˜μ΄μ§€λ„ μ‘΄μž¬ν•œλ‹€. κ·Έλ ‡λ‹€λ©΄ μƒν’ˆλ¦¬μŠ€νŠΈμ—μ„œ μ„ νƒν•œ μƒν’ˆμ˜ 상세 νŽ˜μ΄μ§€μ— μ ‘κ·Ό ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒ?

πŸ’‘ νŠΉμ • κ·œμΉ™μ„ λ§Œλ“€κ³ , κ·Έ κ·œμΉ™κ³Ό λΆ€ν•©ν•˜λŠ” URL이 μžˆμ„ κ²½μš°μ—λ§Œ ν•΄λ‹Ή elementλ₯Ό 화면에 λ³΄μ—¬μ£ΌλŠ” λ°©μ‹μœΌλ‘œ ν•΄κ²°ν•œλ‹€.

URL Parameter

  • /:κ°’ ν˜•νƒœλ‘œ 동적인 데이터λ₯Ό μ „λ‹¬ν•œλ‹€.

  • : 기호 뒀에 λΆ™λŠ” λ¬Έμžμ—΄μ΄ Path Parameter 이닀.

  • Path Parameter λŠ” URL에 μžˆλŠ” 값을 마치 λ§€κ°œλ³€μˆ˜(Parameter)처럼 μ‚¬μš©ν•˜λŠ” 것이닀.

  • Path parameterλ₯Ό μ΄μš©ν•˜λ©΄ μ‚¬μš©μžκ°€ 같은 νŽ˜μ΄μ§€λ‘œ μ ‘μ†ν•˜λ”λΌλ„, 큰 틀은 λ™μΌν•˜λ˜ λ‹€λ₯Έ UIλ₯Ό 보여주도둝 μ²˜λ¦¬ν•  수 μžˆλ‹€.

function App() {

  return (
    <Layout>
      <Routes>
        <Route path={'/'} element={<Home/>}></Route>
        <Route path={'/search'} element={<Search/>}></Route>
        <Route path={'/country/:code'} element={<Country/>}></Route>
        <Route path={'*'} element={<NotFound/>}></Route>
      </Routes>
    </Layout>
  );
}
export default App

βš™οΈ useParams

  • URL Params의 값을 객체 ν˜•νƒœλ‘œ λ°˜ν™˜ν•œλ‹€.

  • key : Route μ—μ„œ μ„€μ •ν•œ Path Parameter의 이름

  • value : Routeμ—μ„œ μ„€μ •ν•œ Path Parameter에 μ‹€μ œλ‘œ μ „λ‹¬λœ κ°’

/post/:id둜 pathλ₯Ό μ„€μ •ν–ˆμ„ λ•Œ, μœ μ €κ°€ /post/1둜 접속할 경우 useParamsκ°€ λ°˜ν™˜ν•˜λŠ” 객체의 keyλŠ” id이고, valueλŠ” 1이닀.

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

export default function Country(){
   const params = useParams();
   console.log(params); // {code : 'KOR'}
   return(
      <div>
         Country! {params.code}
      </div>
   );
}

QueryString

  • URL에 쿼리 μŠ€νŠΈλ§μ„ ν¬ν•¨μ‹œμΌœμ£Όλ©΄ λœλ‹€. νŠΉλ³„ν•œ 섀정을 ν•  ν•„μš”λŠ” μ—†λ‹€.

    • Link μ»΄ν¬λ„ŒνŠΈ μ˜ˆμ‹œ : <Link to="/list?sort=popular" />

    • navigate ν•¨μˆ˜ μ˜ˆμ‹œ : navigate("/list?sort=popular")

βš™οΈ useSearchParams

  • QueryString (예 : ?sort=popular&sort=latest) μ—μ„œ μ›ν•˜λŠ” κ°’λ§Œ κΊΌλ‚΄μ˜¬ 수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” Hook

const [searchParams, setSearchParams] = useSearchParams();
  • searchParams.get(key) : 쿼리 μŠ€νŠΈλ§μ—μ„œ νŠΉμ • key의 value κ°’ λ°˜ν™˜ (ν•˜λ‚˜λ§Œ)

  • searchParams.getAll(key) : 쿼리 μŠ€νŠΈλ§μ—μ„œ νŠΉμ • key의 λͺ¨λ“  value 값을 λ°°μ—΄λ‘œ λ°˜ν™˜

  • searchParams.toString() : 객체 ν˜•νƒœμ˜ 쿼리 μŠ€νŠΈλ§μ„ λ¬Έμžμ—΄ ν˜•νƒœλ‘œ λ°˜ν™˜

πŸ”— μ°Έκ³ 

Last updated