๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[๊ฐœ๋ฐœ] Practice/React

[React] React Router : ์…‹ํŒ… ํ›„ ๊ธฐ๋ณธ ๋ผ์šฐํŒ…ํ•ด๋ณด๊ธฐ

by Connecting-the-dots 2022. 3. 24.
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ’ก ์‹ค์Šต ํฌ์ธํŠธ!

๐Ÿ’œ ๋ฉ”์ธ ํŽ˜์ด์ง€( ๊ฒฝ๋กœ : / )


๐Ÿ’œ ์ƒ์„ธ ํŽ˜์ด์ง€ ( ๊ฒฝ๋กœ : /detail )


๐Ÿ’œ React Router ์…‹ํŒ… ํ›„ ๊ธฐ๋ณธ ๋ผ์šฐํŒ…ํ•ด๋ณด๊ธฐ

  • ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ์—๋Š” Router ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์ด๋Š” react-router-dom ์ด๋ผ๋Š” ๊ณต์‹ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜๋ฅผ ํ†ตํ•ด ์ด์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿค React Router ์„ค์น˜ ๋ฐ ์…‹ํŒ…

// npm ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
npm install react-router-dom@5.2.0

// yarn ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
yarn add react-router-dom@5.2.0
  • ํ„ฐ๋ฏธ๋„์— ์œ„ ๋‘ ์ฝ”๋“œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ž…๋ ฅํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋œ๋‹ค.
  • yarn ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฏธ๋ฆฌ yarn ์ด ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom'; // ์ถ”๊ฐ€

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter> // ์ถ”๊ฐ€
      <App />
    </BrowserRouter> // ์ถ”๊ฐ€
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();
  • ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด index.js ํŒŒ์ผ์˜ ๊ธฐ์กด ์ฝ”๋“œ์— ์œ„์™€ ๊ฐ™์ด ๋ช‡ ๊ฐ€์ง€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

๐Ÿ“Œ HashRouter

  • ์…‹ํŒ…ํ•  ๋•Œ BrowserRouter ๋ง๊ณ  HashRouter ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • Browser ๋ผ๋Š” ๋‹จ์–ด ๋Œ€์‹  Hash ๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • BrowserRouter ์™€ HashRouter ์˜ ์ฐจ์ด์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
    • HashRouter ๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์—๋Š” ์‚ฌ์ดํŠธ์— ์ ‘์† ์‹œ  URL ๋งจ ๋์— /#/ ์ด ๋ถ™์€ ์ฑ„๋กœ ์‹œ์ž‘ํ•œ๋‹ค.
    • BrowserRouter ๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์—๋Š” ์‚ฌ์ดํŠธ์— ์ ‘์† ์‹œ URL ์ด ๊น”๋”ํ•˜๋‹ค.
  • ๊ทธ๋Ÿผ์—๋„ HashRouter ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
    • ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์ฐฝ์— ์–ด๋–ค ํŽ˜์ด์ง€๋ฅผ ์ž…๋ ฅํ•˜๋Š” ํ–‰์œ„๋Š” ์„œ๋ฒ„์— ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ๋‹ฌ๋ผ๋Š” ์š”์ฒญ์ด๋‹ค.
    • ํ˜„์žฌ ๋‚ด๊ฐ€ ๋งŒ๋“œ๋Š” ํ”„๋กœ์ ํŠธ๋Š” ์š”์ฒญํ•  ์„œ๋ฒ„๊ฐ€ ์—†๊ณ  ๋ฆฌ์•กํŠธ๊ฐ€ ๋ผ์šฐํŒ…์„ ๋‹ด๋‹นํ•˜๋ฏ€๋กœ, ์ž˜๋ชปํ•ด์„œ ์žˆ์ง€๋„ ์•Š์€ ํŽ˜์ด์ง€๋ฅผ ์„œ๋ฒ„์— ์š”์ฒญํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋œฐ ์ˆ˜ ์žˆ๋‹ค.
    • ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์ฐฝ์—์„œ # ๋’ค์— ๋ถ™์€ ๋‚ด์šฉ์€ ์ ˆ๋Œ€ ์„œ๋ฒ„๋กœ ์š”์ฒญ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์‹ค์ˆ˜๋กœ ์„œ๋ฒ„์— ์š”์ฒญํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ์•ˆ์ „ํ•˜๊ฒŒ # ์„ ๋ถ™์—ฌ์ฃผ๋Š” ๊ฒŒ ์ข‹์œผ๋ฉฐ ๊ทธ ์—ญํ• ์„ HashRouter ๊ฐ€ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๊ณ  ํ•ด์„œ ๊ผญ HashRouter ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ , BrowserRouter ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํŠน์ • ๊ฒฝ๋กœ์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ ๋ฆฌ์•กํŠธ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก API ๋ฅผ ๋งŒ๋“ค์–ด๋†“์œผ๋ฉด ๋œ๋‹ค. ์ฆ‰, ์„œ๋ฒ„์—์„œ ์…‹ํŒ…๋งŒ ์ž˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿค ๋ผ์šฐํŒ…์œผ๋กœ ํŽ˜์ด์ง€ ๋‚˜๋ˆ„๊ธฐ

  • / ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•˜๋ฉด ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ, /detail ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•˜๋ฉด ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ ‘์†์ด ๋˜๋„๋ก ํ•ด๋ณด์ž.
import { Link, Route, Switch } from 'react-router-dom';

 

  • ๋ผ์šฐํŒ…์„ ํ•ด์ฃผ๊ธฐ ์ „์— ๋จผ์ € App.js ํŒŒ์ผ์— ์œ„์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํƒœ๊ทธ๋“ค์„ import ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
import { Link, Route, Switch } from 'react-router-dom';

function App(){
  return (
    <div>
      <Route exact path="/"> 
        <div>๋ฉ”์ธ ํŽ˜์ด์ง€</div>
      </Route>
      <Route path="/detail">
        <div>์ƒ์„ธ ํŽ˜์ด์ง€</div>
      </Route>
    </div>
  )
}
  • ๋‹ค์Œ์œผ๋กœ ๋ผ์šฐํŒ…์„ ํ•˜๊ธฐ ์œ„ํ•ด ์›ํ•˜๋Š” ๊ณณ์— <Route></Route> ํƒœ๊ทธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  <Route> ์•ˆ์— path ์™€ path ๋ฐฉ๋ฌธ์‹œ ๋ณด์—ฌ์ค„ HTML ์„ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ์ด ๋•Œ "๋ฉ”์ธ ํŽ˜์ด์ง€" ๋ฌธ๊ตฌ๋ฅผ ๋ณด์—ฌ์ค„ <Route> ์•ˆ์˜ path ์—๋Š” exact ๋ฅผ ๋ถ™์—ฌ์„œ ์ •ํ™•ํ•˜๊ฒŒ / ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•ด์•ผ์ง€๋งŒ ๋ฉ”์ธ ํŽ˜์ด์ง€๊ฐ€ ๋ณด์ด๊ฒŒ ํ•ด์ฃผ์—ˆ๋‹ค.
    (exact ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด /detail ์ด๋ผ๋Š” ๊ฒฝ๋กœ์— / ๋ผ๋Š” ๋ฌธ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ "๋ฉ”์ธ ํŽ˜์ด์ง€" ๋ผ๋Š” ๋ฌธ๊ตฌ์™€ "์ƒ์„ธ ํŽ˜์ด์ง€" ๋ผ๋Š” ๋ฌธ๊ตฌ๋ฅผ ๋ชจ๋‘ ๋ณด์—ฌ์ฃผ๊ฒŒ ๋˜๋ฉฐ, React Router ๋Š” ์›๋ž˜ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.) 
  • ์ด์ œ ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์ฐฝ์—์„œ / ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•˜๋ฉด "๋ฉ”์ธ ํŽ˜์ด์ง€", /detail ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ•˜๋ฉด "์ƒ์„ธ ํŽ˜์ด์ง€" ๋ผ๋Š” ๋ฌธ๊ตฌ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
<Route path="/grid" component={ Grid } ></Route>
  • ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์„œ /grid ๋ผ๋Š” ๊ฒฝ๋กœ๋กœ ์ ‘์†ํ–ˆ์„ ๋•Œ ๋งŒ๋“ค์–ด๋†“์€ Grid Component ๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.
<Route path="/grid"> <Grid/> </Route>
  • ๋ฌผ๋ก  component ์†์„ฑ ์—†์ด <Route></Route> ํƒœ๊ทธ ์‚ฌ์ด์— Grid Component ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด๋„ ๋œ๋‹ค.

๐Ÿ“Œ React Router ์˜ ํŠน์ง•

  • ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋‹ค๋ฅธ HTML ํŒŒ์ผ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ HTML ํŒŒ์ผ ๋‚ด๋ถ€์˜ ๋‚ด์šฉ์„ ๋ฐ”๊พธ์–ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํ‰๋‚ด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.

๐Ÿค ๋ฉ”์ธ ํŽ˜์ด์ง€์™€ ์ƒ์„ธ ํŽ˜์ด์ง€ Route ์— ๋‚ด์šฉ ์ฑ„์šฐ๊ธฐ

  • ๋ฉ”์ธ ํŽ˜์ด์ง€๋Š” Router ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ„์™€ ๊ฐ™์€ ํ™”๋ฉด์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์—ˆ๋‹ค.
import React, {useState} from 'react';

function Main(props) {

    return (
        <>
        {/* Main */}
        <div className="main-visual">
          <h2>Welcome to visit SHOES.COM!</h2>
          <hr/>
          <h1>20% Season Off</h1>
          <button>SHOP THIS DEAL</button>
        </div>

        {/* Grid */}
        <div className="container">
          <div className="row">

            {
            props.shoes.map((item, idx)=>{
              return (
                <Grid shoes={props.shoes[idx]} key={idx} />
                )
              })
            }

          </div>
        </div>
        </>
    )
}

function Grid(props) {
    return (
      <div className="col-md-4 grid">
        <img src={`https://codingapple1.github.io/shop/shoes${props.shoes.id + 1}.jpg`} />
        <h5>{props.shoes.title}</h5>
        <p>{props.shoes.content} & {props.shoes.price}</p>
      </div>
    )
}

export default Main;
  • ํ™”๋ฉด์ƒ์œผ๋กœ๋Š” ๋™์ผํ•˜์ง€๋งŒ ํŽ˜์ด์ง€๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒŒ ๋ชฉ์ ์ด์—ˆ์œผ๋ฏ€๋กœ <Route></Route> ๋ฅผ ์ด์šฉํ•ด์•ผํ–ˆ๋‹ค.
  • <Route></Route> ์•ˆ์— ๊ธฐ์กด์— ์ž‘์„ฑํ•ด๋‘” ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ๋„ฃ์œผ๋ ค๋‹ˆ ๋„ˆ๋ฌด ๋งŽ์•„์„œ Navbar ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋ฉ”์ธ ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๋‚ด์šฉ๋งŒ ๋‹ด์€ Main.js ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์ฃผ์—ˆ๋‹ค.
  • Main.js ํŒŒ์ผ์—์„œ Main ์ด๋ผ๋Š” Component ๋ฅผ ๋งŒ๋“  ํ›„ Main ์ด๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์œผ๋กœ export ํ•ด์ฃผ์—ˆ๋‹ค.
// ์ „์ฒด ์ฝ”๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
// ์ „์ฒด ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์ œ์™ธํ–ˆ๋‹ค.

import Main from './Main'

function App() {

  let [shoes, setShoes] = useState(Data);
  
  return (
    <div className="App">

          {/* Main */}
          <Route exact path='/'>
            <Main shoes={shoes}/>
          </Route>
    
    </div>
  );
}
  • ์ด์ œ App.js ์—์„œ Main.js ํŒŒ์ผ์—์„œ Main ์ด๋ผ๋Š” Component ๋ฅผ import ํ•ด์ฃผ์—ˆ๋‹ค.
  • ๊ทธ๋‹ค์Œ <Route></Route> ํƒœ๊ทธ ์‚ฌ์ด์— Main Component ๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.
  • ์ด ๋–„, Main Component ์—์„œ shoes ๋ผ๋Š” state ๋ฅผ ๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก shoes ๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์œผ๋กœ shoes ๋ผ๋Š” state ๋ฅผ ์ „์†กํ•ด์ฃผ์—ˆ๋‹ค.
    (Main.js ์—์„œ๋Š” Main Component ์— props ๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ shoes ๋ฅผ ๋ฐ›์•„์˜ค๋ฉด ๋œ๋‹ค.)

 

<div className="container">
      <div className="row">
        <div className="col-md-7">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-5 mt-4">
          <h4 className="pt-5">White and Black</h4>
          <p>Born in France</p>
          <p>120000</p>
          <button className="btn btn-danger mx-1">์ฃผ๋ฌธํ•˜๊ธฐ</button> 
          <button className="btn btn-danger mx-1">๋’ค๋กœ๊ฐ€๊ธฐ</button> 
        </div>
      </div>
</div>
  • ์ƒ์„ธ ํŽ˜์ด์ง€๋Š” ๋‚˜์ค‘์— ๋ถ„๋ฆฌํ•  ์˜ˆ์ •์ด๋ผ ์œ„ ์ฝ”๋“œ๋ฅผ <Route></Route> ์•ˆ์— ๋ฐ”๋กœ ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•