React Router(리액트 라우터) - 1

Jonghan·2020년 4월 24일
8

react

목록 보기
2/5

리액트 라우터

전 시간에도 다뤘기 때문에 간략하게만 적고 가겠다.

다른 주소에 다른 화면을 보여준다. - 라우팅

라우팅 라이브러리는 크게 3개가 있는데 (혹시 몰라 신흥강자가 나타났을지도. 근데 일단 난 모름)
리액트 라우터, 리치 라우터, Next.js 가 바로 그것이다.
만약 리치 라우터의 리치가 Rich였으면 난 주저않고 리치 라우터를 썼겠지만, 아쉽게도 Reach다.

이 중에 가장 역사가 오래되기도 했고, 나중에 익혀볼 서버 사이드 렌더링에 적합하며 가장 많이 쓰이는 리액트 라우터를 알아보자.

어떻게 쓸까

yarn add react-router-dom

일단, 리액트가 공식적으로 지원하는 라우터 기능이 없기 때문에 라이브러리를 설치해야 한다.
당연히 이걸 설치하기 전에 리액트 프로젝트부터 CRA를 통해 만들어두자.

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

그 후 src/index.js파일에서 저 부분을 다음과 같이 바꿔보자.

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

(... 중략)

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

BrowserRouter란 뭘까? HTML5History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경할 수 있도록 해준다.(즉, 페이지 변경으로 인한 깜빡거림이 없다.)
또, 현재 주소에 관련된 정보를 props로 조회 및 사용이 가능하도록 만들어준다.

// Home.js
import React from 'react';

/**
 * 함수형 컴포넌트 스니펫입니다.
 */
const Home = () => {
  return (
    <div>
      <h1>Home</h1>
      <p>Take me home~ Country road~</p>
    </div>
  );
};

export default Home;

src 디렉토리에 Home.js파일을 만들어보자. 또, About.js도 만들어보자.

// About.js
import React from 'react';

/**
 * 함수형 컴포넌트 스니펫입니다.
 */
const About = () => {
  return (
    <div>
      <h1>열정적으로 살고 싶다.</h1>
      <p>리액트 라우터 한 방에 끝내버리자.</p>
    </div>
  );
};

export default About;

당연한 얘기지만 안의 내용물은 마음대로 적어도 된다. 저거 바꾼다고 결과에 아무런 지장이 없다.

import React from 'react';
import About from './About';
import Home from './Home';

function App() {
  return (
    <div>
      <Home />
      <About />
    </div>
  );
}

export default App;

홈을 이렇게 만들고, yarn start를 통해서 리액트 렌더링을 해보자.

결과값은 다음과 같고 하나하나 설명해보겠다.

  • index.js에서 ReactDOM.render(<App />)를 썼기 때문에 localhost:3000에는 App.js 컴포넌트가 렌더링이 된다.
  • Home, About 컴포넌트를 모두 App의 자식 컴포넌트로 집어넣었기 때문에, 둘 다 출력이 된다.

하지만 우리가 원하는 것은 이게 아니다. localhost:3000에선 Home 컴포넌트가, localhost:3000/about에선 About 컴포넌트가 렌더링되었으면 좋겠다.

Route

import React from 'react';
import About from './About';
import Home from './Home';
import { Route } from 'react-router-dom';

function App() {
  return (
    <div>
      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
    </div>
  );
}

export default App;

App.js를 위와같이 바꿔보자. Route라는 못 보던 컴포넌트가 보이는데, 이게 바로 주소에 따라 다른 화면을 보여주는 라우팅 기능을 가진 컴포넌트이다. path=""부분에는 바뀔 주소의 이름을 적고, component={}부분에는 렌더링될 컴포넌트를 집어넣는다.

<Route path="/이동할 주소" component={출력할 컴포넌트}/>

나같은 경우는 위에 내가 원했던 것처럼 메인에선 Home.js가 뜨길 바랐고, /about에선 About.js에서 뜨길 바랐으니 위와같이 코드를 적었다.

결과값은 다음과 같다.

보다시피 About 컴포넌트가 지워진 것을 알 수 있다. 메인화면에선 Home 컴포넌트만 렌더링 되도록 설정해놨기 때문이다.

다음은 /about으로 이동해 페이지 렌더링이 완료된 모습인데, 뭔가 이상하다.

분명 나는 Home 컴포넌트를 이 주소에 넣어준 기억이 없는데 이 놈은 왜 출력된걸까?
왜냐하면 /about/가 들어있기 때문이다. 그래서 둘 다 포함이 되니까 출력된 것
이 것은 exact라는 옵션으로 해결이 가능하다.

<Route path="/이동할 주소" component={출력할 컴포넌트} exact/>

아, 여기서 주의할 점은 About쪽 Route를 바꾸는게 아니라, Home쪽을 바꿔줘야 한다.

exact의 의미는 정확히 이 path에서만 해당 라우팅을 이뤄지도록 하라는 명령인데, 원래는 exact={true}가 맞지만, true는 생략해도 된다는 건 리액트의 기초.

    <div>
      <Route path="/" component={Home} exact />
      <Route path="/about" component={About} />
    </div>

다음과 같이 App.js를 수정해주고 결과를 다시 확인해보자

아주 잘 나온다.

<a href="localhost:3000/about">와 같은 태그를 사용할 경우에도 위와 동일한 결과가 나오겠네?

아니, 사용하면 안 된다. Route를 사용하는 이유는 현재 페이지에서 상태를 유지하면서 바뀐 주소에 따라 바뀐 화면만 보이고 싶을 뿐인데, a태그를 사용할 경우, 상태가 전부 날라가버린다. 또 기존의 렌더링된 컴포넌트를 다 날려버리고 처음부터 렌더링이 진행된다.

위에서 썼던 이 부분을 기억하자.

HTML5History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경할 수 있도록 해준다.(즉, 페이지 변경으로 인한 깜빡거림이 없다.)

이 부분은 <a>로는 구현이 안 된다. BrowserRouter를 이용한 다른 무언가를 사용해야 한다. 그게 바로 Link다.

Link 컴포넌트는 클릭하면 다른 주소로 이동하는 과정에서 페이지를 새로 불러오지 않고 유지한 상태에서 History API만을 사용하여 페이지의 주소만 변경해준다. Link 컴포넌트는 한마디로 a의 상속버전이라고 봐도 무방한데, 컴포넌트 자체로는 a로 이뤄져 있지만, 추가적으로 페이지 전환을 방지하는 기능이 들어있다.

<Link to='이동할주소'>내용</Link>

사용법은 위와 같다.

Route를 사용했을때는, 우리가 직접 URL을 주소창에 입력해야지만 다른 페이지로 넘어갈 수 있었다. 하지만 어떤 X신같은 웹사이트도 그런식으로 주소 이동을 하진 않는다. 로그인을 하려고 로그인 버튼을 누르는게 아니라 http://localhost:3000/login을 쳐서 들어가게 만들진 않는다는 얘기다. 그런 사이트가 있다면 아무도 안 쓸듯.

그래서 보통은 <a>태그를 많이 쓰는데 그냥 그걸 <Link>가 대신해준다고 보면 된다.

    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">어바웃</Link>
        </li>
      </ul>
      <Route path="/" component={Home} exact />
      <Route path="/about" component={About} />
    </div>

App.js를 다음과 같이 작성하게 되면 a태그를 쓴 것 처럼 다음 화면이 나온다.

홈 버튼을 누르면 localhost:3000 어바웃을 누르면 localhost:3000/about으로 이동한다.

그럼 라우팅 Route에 따라 현재 주소가 localhost:3000/aboutcomponent={About}이므로 About 컴포넌트를 출력한다.

1 Route N paths

하나의 라우트에 여러가지 패스를 정해줄 수가 있는데, 즉 URL 입력을 여러 개로 해도 동일한 컴포넌트가 렌더링 되도록 할 수 있다.

      <Route path={['/about', 'hi']} component={About} />

위와 같이 적으면 http://localhost:3000/hi일때도 About 컴포넌트가 렌더링 된다.
path부분에는 배열이라는 자바스크립트 코드가 들어가므로 {}로 감싸는 것을 잊어선 안 되겠다.

마치며

글의 길이가 좀 길어질 것 같아, 다음 글로 포스팅을 미루겠다.

profile
열정적으로 살고 싶다.

2개의 댓글

comment-user-thumbnail
2021년 3월 22일

감사합니다. 제가 찾던 내용이네요.

“'Link' is not defined react/jsx-no-undef” 에러나시는 분들은
import { Route, Link } from 'react-router-dom';
추가하시면 됩니다.

답글 달기
comment-user-thumbnail
2021년 8월 21일

Error: Invariant failed: You should not use outside a
이런 에러 납니다.

답글 달기