본문 바로가기
React

[리액트] react-router-dom v5 사용법

by 메이플 🍁 2022. 4. 11.

⚠️ 이 포스팅은 김민준님의 리액트를 다루는 기술 스파르타코딩클럽 리액트 기초반을 공부하고 정리한 블로그 포스팅입니다. ⚠️

 

포스팅에 해당하는 목차는 다음과 같습니다:

리액트를 다루는 기술

  • 13장 리액트 라우터로 SPA 개발하기

 

리액트 기초반

  • 3-3 리액트에서 라우팅 처리하기 (1)
  • 3-4 리액트에서 라우팅 처리하기 (2)

 


 

1. react-router-dom 라이브러리 v5 설치하기

yarn add react-router-dom@5.2.1

 

2. index.js에 BrowserRouter 적용하기

<BrowserRouter>로 프로젝트에 라우터를 적용한다. <BrowserRouter> 컴포넌트는 1) 사용자가 입력한 주소를 감지하는 역할 2) 여러 종류의 라우터 컴포넌트를 제공 3) 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경할 수 있게 함 4) 현재 주소에 관련된 정보를 props 로 쉽게 조회하거나 사용할 수 있도록 해줌

<BrowserRouter> 컴포넌트 내부에 있는 컴포넌트는 라우터 기능을 사용할 수 있게된다. 아래 예제에서는 가장 최상위 컴포넌트인 App을 <BrowserRouter>로 감싸주면 App의 자식 컴포넌트에서도 라우터 기능을 적용시켰다. 특정 컴포넌트에만 라우터 기능을 부여하고 싶다면 라우터 기능을 부여하고 싶은 컴포넌트에만 <BrowserRouter> 컴포넌트로 감싸주면 된다.

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(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

reportWebVitals();

BrowserRouter가 너무 길다고 느껴지면 as를 사용해 별명을 지정해주자

BrowserRouter를 사용하고 싶을때 별명으로 지정했던 Router를 대신 사용할 수 있다.

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

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById('root')
);

ReactDOM.render() 코드

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

ReactDOM.render(첫번째 파라미터, 두번째 파라미터)

  • 첫번째 파라미터: 무엇을 렌더시킬까 → 최상위 컴포넌트 <App>
  • 두번째 파라미터: 어디에 렌더시킬까 → id가 root인 element 즉 public > index.html에 있는 id가 root인 요소

 

2. 세부 화면 만들기

Home.js

import React from 'react';

const Home = props => {
  return <div>메인 화면이에요.</div>;
};

export default Home;

Cat.js

import React from 'react';

const Cat = props => {
  return <div>고양이 화면이에요.</div>;
};

export default Cat;

Dog.js

import React from 'react';

const Dog = props => {
  return <div>강아지 화면이에요.</div>;
};

export default Dog;

 

3. App.js에서 Route 적용하기

3.1 Route 컴포넌트로 특정 주소에 컴포넌트 연결하는 2가지 방법

방법 1: Route의 children으로

<Route> 컴포넌트가 해당 컴포넌트를 children으로 감싸고 있는 형태라면 props가 없기 때문에 사용하고 싶은 훅을 import한다.

<Route path='주소'>
  <보여줄컴포넌트/>
</Route>

방법 2: component의 props로

props를 사용하기 위해서는 <Route> 컴포넌트에 props값으로 해당 컴포넌트를 전달해줘야한다.

<Route path='주소' component={보여줄컴포넌트} />

3.2 Route 적용하기

브라우저 주소창에 있는 주소와 path안에 있는 주소가 같을 경우 안에 들어 있는 컴포넌트를 보여준다.

  • 브라우저 주소창: domain/
  • 보여질 컴포넌트: <Route>의 path가 "/"인 컴포넌트 <Home>

방법 1: Route의 children으로

App.js 

import { Route } from 'react-router-dom';
import Home from '../Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      <Route path='/'>
        <Home />
      </Route>
      <Route path='/cat'>
        <Cat />
      </Route>
      <Route path='/dog'>
        <Dog />
      </Route>
    </div>
  );
}

export default App;

방법 2: component의 props로

App.js

import { Route } from 'react-router-dom';
import Home from '../Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      <Route path='/' component={Home} exact />
      <Route path='/cat' component={Cat} />
      <Route path='/dog' component={Dog} />
    </div>
  );
}

export default App;

domain/cat 결과창

  • 문제점: path가 "/cat"인 <Route>안에 있는 컴포넌트 <Cat>만 보여지는 것이 아닌 컴포넌트 <Home>도 같이 보여진다.
  • 이유: 경로의 앞부분만 일치해도 매칭되는 것으로 간주되기 때문이다. 예제에서 path="/cat"이 도메인 "/"도 포함하고 있기 때문에 해당하는 컴포넌트 <Home>도 같이 렌더링이 되었다. 
  • 해결법: 정확히 라우트를 일치시키기 위해 Route에 exact 옵션을 사용한다.

 

4. exact 옵션 적용하기

exact 옵션을 적용하면 주소창의 URL과 path의 URL이 완전히 일치할 경우에만 화면에 렌더링시켜준다.

App.js

import { Route } from 'react-router-dom';
import Home from './Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      { /* exact 옵션 적용하기 */ }
      <Route path='/' exact>
        <Home />
      </Route>
      <Route path='/cat'>
        <Cat />
      </Route>
      <Route path='/dog'>
        <Dog />
      </Route>
    </div>
  );
}

export default App;

domain/cat 결과창

 

5.  path 주소창에 URL 파라미터 사용하기

5.1 동적 라우팅 (Dynamic Routing)이란?

페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야할 때도 있다. 이때 라우터의 경로에 유동적인 값인 URL 파라미터나 쿼리를 넣어서 특정 페이지로 이동하는데 이것을 동적 라우팅이라고 한다.

1) URL 파라미터

  • 특정 아이디, 이름을 사용하여 조회할 때 사용
domain/profile/maple

2) 쿼리 (쿼리 스트링)

  • 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분을 하는 형태
  • 어떤 키워드를 검색할때
  • 페이지에 필요한 옵션을 전달할 때
domain/about?page=1&keyword=react

 

5.2 URL 파라미터 주기

Route의 path에 :cat_name라는 파라미터를 넣어주면 cat_name에 들어가는 값은 동적으로 바뀐다. 즉 주소창에 domain/cat/navi로도 Cat 컴포넌트에 접근할 수 있고 domain/cat/samsaek이라는 주소로도 Cat 컴포넌트에 접근할 수 있다는 의미다.

component의 props로 라우터 적용했을때 URL 파라미터 주기

<Route path='/cat/:cat_name' component={Cat}/>

Route의 children으로 라우터 적용했을때 URL 파라미터 주기

<Route path='/cat/:cat_name'>
  <Cat />
</Route>

 

5.3 URL 파라미터에 접근하기

방법 1: props로 URL 파라미터에 접근하기

App.js (component의 props로 라우터 적용했을때)

props를 사용하기 위해서는 컴포넌트에 props값으로 해당 컴포넌트를 전달해줘야 한다. 

import { Route } from 'react-router-dom';
import Home from './Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      <Route path='/' component={Home} exact />
      <Route path='/cat/:cat_name' component={Cat} />
      <Route path='/dog' component={Dog} />
    </div>
  );
}

export default App;

Cat.js

전달받은 props를 콘솔창에 출력한다.

import React from 'react';

const Cat = props => {
  console.log(props);

  return (
    <>
      <div>고양이 화면이에요.</div>
    </>
  );
};

export default Cat;

콘솔창

주소창에 domain/cat/samsaek이라고 입력했을때 props는 아래의 정보를 가져온다. 즉 동적 URL 파라미터인 cat_name을 사용하기 위해서는 props.match.params에 접근해야한다.

props.match.params로 props로 받아온 URL 파라미터 접근하기

console.log(props.match.params);

 

방법 2: useParams 훅으로 URL 파라미터에 접근하기

App.js (Route의 children으로 라우터 적용했을때)

<Route> 컴포넌트가 해당 컴포넌트를 children으로 감싸고 있는 형태라면 props를 사용할 수 없으므로 useParams 훅을 사용해 URL 파라미터에 접근해준다.

import { Route } from 'react-router-dom';
import Home from './Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      <Route path='/' exact>
        <Home />
      </Route>
      <Route path='/cat/:cat_name'>
      	<Cat />
      </Route>
      <Route path='/dog'>
        <Dog />
      </Route>
    </div>
  );
}

export default App;

Cat.js

웹브라우저 주소창에 도메인/cat/samsaek이라고 접속하면 useParams 객체에 cat_name이라는 key값 samsaek이라는 value가 할당된다.

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

const Cat = () => {
  const cat_name = useParams();
  console.log(cat_name);

  return (
    <>
      <div>고양이 화면이에요.</div>
    </>
  );
};

export default Cat;

콘솔창

usePrarms 훅을 사용하면 훨씬 간단하게 URL 파라미터에 접근할 수 있다.

 

6. 다른 주소로 이동하기

1) <Link> 컴포넌트 사용해서 페이지 이동하기

리액트 라우터에서 a 태그를 사용해 페이지를 이동하면 페이지를 처음부터 다시 새로 불러오기 때문에 사용할 수 없다. 대신 a 태그와 비슷한 역할을 하는 Link 컴포넌트를 사용해 페이지를 이동시켜준다. Link 컴포넌트를 사용해 페이지를 이동하면 애플리케이션은 그대로 유지한 상태에서 HTML5 History API를 사용해 페이지의 주소만 변경해준다. 즉 Link 컴포넌트에는 페이지 전환을 방지하는 기능이 내장되어 있어 기존 상태를 유지할 수 있다.

Link 컴포넌트 문법

<Link to="주소">[텍스트]</Link>

App.js

Link 컴포넌트의 바깥에 있는 돔요소는 페이지가 전환되어도 그대로 유지된다. 메뉴를 Route 바깥에 만들어 페이지가 전환되도 메뉴링크가 화면에 항상 있도록 만들어준다.

import { Route, Link } from 'react-router-dom';
import Home from './Home';
import Cat from './Cat';
import Dog from './Dog';

function App() {
  return (
    <div className="App">
      <ul>
        <li>
          <Link to="/">Home으로 가기</Link>
        </li>
        <li>
          <Link to="/cat">Cat으로 가기</Link>
        </li>
        <li>
          <Link to="/dog">Dog으로 가기</Link>
        </li>
      </ul>
      <Route path='/' component={Home} exact />
      <Route path='/cat' component={Cat} />
      <Route path='/dog' component={Dog} />
    </div>
  );
}

export default App;

 

2) history 사용해서 페이지 이동하기

props로 전달받는 history 객체는 특정 버튼을 눌렀을때 뒤로 가거나, 로그인 후 화면을 전환할때 주로 사용한다.

방법 1: props로 history 객체를 받아 페이지 이동하기

Cat.js

props 안에 있는 history 객체에 접근해 push 라는 메서드를 사용해준다. push 메서드는 이동할 path를 인자로 적어주기면 해당 페이지로 이동이 가능하다.

import React from 'react';

const Cat = props => {
  console.log(props);

  return (
    <>
      <div>고양이 화면이에요.</div>
      <button
        onClick={() => {
          props.history.push('/dog');
        }}
      >
        강아지 화면으로 돌아가기
      </button>
    </>
  );
};

export default Cat;

방법 2: useHistory 훅을 사용해 페이지 이동하기

Cat.js

Route의 children으로 컴포넌트를 연결시켜주었을때는 전달해줄 props가 없으므로 history 객체도 사용할 수 없다. 대신 history 객체의 기능을 가지고 있는 useHistory 훅을 사용해 페이지 이동시켜준다. history 객체와 마찬가지로 push 메서드의 인자로 이동할 path를 전달하면 해당 페이지로 이동이 가능하다.

import React from 'react';
import { useHistory } from 'react-router-dom';

const Cat = () => {
  let history = useHistory();
  return (
    <>
      <div>고양이 화면이에요.</div>
      <button
        onClick={() => {
          history.push('/dog');
        }}
      >
        강아지 화면으로 돌아가기
      </button>
    </>
  );
};

export default Cat;

 

8. Switch를 사용해서 NotFound 페이지 구현하기

Switch는 여러 Route들을 감싸서 그 중 규칙이 일치하는 라우트 단 하나만을 렌더링시켜준다. Switch를 사용하면, 아무것도 일치하지 않았을때 보여줄 Not Found 페이지를 구현할수도 있다.

NotFound.js

import React from 'react';

const NotFound = () => {
  return <div>페이지를 찾을 수 없습니다</div>;
};

export default NotFound;

App.js

import { Route, Link, Switch } from 'react-router-dom';
import Home from './Home';
import Cat from './Cat';
import Dog from './Dog';
import NotFound from './NotFound';

function App() {
  return (
    <div className="App">
      <ul>
        <li>
          <Link to="/">Home으로 가기</Link>
        </li>
        <li>
          <Link to="/cat">Cat으로 가기</Link>
        </li>
        <li>
          <Link to="/dog">Dog으로 가기</Link>
        </li>
      </ul>
      <Switch>
        <Route path='/' component={Home} exact />
        <Route path='/cat' component={Cat} />
        <Route path='/dog' component={Dog} />
        <Route component={NotFound} />
      </Switch>
    </div>
  );
}

export default App;

 

댓글