개인공부/TIL(Today I Learned)

TIL 73일차_React Router

soon327 2021. 4. 1. 01:57

Why React Router?

리액트로 라우팅을 구현하는 방법이 무엇이 있을까?
가장 쉽게 떠올릴 수 있는 방법은,
이벤트에 따라 상태를 달리주고 새로 렌더시키는 것이다.

그러나 이렇게하면 사용자입장에서 다음과 같은 문제가 발생하게된다.

  1. 특정 페이지에 대한 즐겨찾기 등록이 불가능하다. 컴포넌트가 전환되더라도 브라우저 주소창의 URL은 고정되어 있기 때문이다.
  2. 뒤로 가기 버튼을 누르면 해당 앱내에서 이전 페이지로 이동하는 것이 아니라 그 전에 서핑하던 다른 웹사이트로 이동해버린다.
  3. 새로 고침 버튼을 누르면 사용 중이던 컴포넌트가 아닌 무조건 최초에 렌더링되었던 Home 컴포넌트로 이동한다.
  4. 또한 SEO(검색 엔진 최적화) 측면에서도 일반 웹사이트들과 차이가 있어서 검색 엔진에 의해 원치않는 방식으로 색인이 될 수도 있다.

React Router는 위와같은 SPA의 라우팅문제를 해결하기위해서 거의 표준처럼 사용하고 있는 네비게이션 라이브러리이다.
React Router를 사용하면, 앱에서 발생하는 라우팅이 location이나 history와 같은
브라우저 내장API와 완벽하게 연동된다.
따라서 SPA에서 제공하는 사용자경험을 그대로 살리면서도 기존 웹사이트에서 가능하던 브라우저상의 매끈한 라우팅을 제공할 수 있다.

React Router 설치(Web용)

$ npm install react-router-dom

React Router 핵심 컴포넌트 3가지

Link 컴포넌트

HTML의 <a>태그와 유사하다.
<a> 태그는 href속성을 사용하는 반면,
<Link> 컴포넌트는 to prop을 통해 이동할 경로를 지정해준다.

<Link to = "/user"> User </Link>

위의 코드는, 브라우저에서 클릭이 가능한 User으로 랜더링되고, User을 클릭하면,
주소창의 경로가 <도메인 네임>/user으로 갱신된다.
일반적으로 환면 상단이나, 좌측에 위치한 네비게이션바를 구현할 때 주로 사용하게되는 컴포넌트이다.

Route 컴포넌트

<Route> 컴포넌트는 현재 주소창의 경로일 때 랜더링할 컴포넌트를 지정하는데 사용된다.
path prop을 통해서 매치시킬 경로를 정하고, component prop을 통해 매치되었을 때 보여줄 컴포넌트를 할당한다.

<Route path = "/coin" component = {Coin} />

위의 코드는, 주소창의 url이 /coin일 경우 Coin라는 컴포넌트를 랜더링한다.
일반적으로 현재 URL에 따라 특정 컨텐츠를 보여주거나 숨기기 위해 사용될 수 있다.

Router 컴포넌트

<Router> 컴포넌트는 위에 나온 <Route><Link> 컴포넌트가 함께 유기적으로 동작하도록 묶어주는데 사용한다.
다시 말해, <Route><Link> 컴포넌트는 DOM 트리 상에서 항상 <Router>를 공통 상위 컴포넌트로 가져야한다.

<Router>
  ...
  <Link />
  <Link />
  ...
  <Router />
  <Router />
  ...
</Router>

실제 프로젝트에서는 위 컴포넌트들이 여러 파일에 걸쳐서 흩어져 있을 수도 있겠지만,
이 큰 그림을 염두해두고 코드를 읽다보면 어렵지 않게 라우팅 흐름을 파악하실 수 있다.

React Router로 라우팅 구현할 때, 주의점

import

import { Link, Route, BrowserRouter as Router } from "react-router-dom"

router에는 BrowserRouter, HashRouter 가 있는데, 최근에는 BrowserRouter가 많이 쓰인다.

exact prop

<header>
  <Link to="/">
    <button>Home</button>
  </Link>
   <Link to="/users">
    <button>Users</button>
  </Link>
</header>

React Router의 디폴트 매칭 규칙 때문에
exact prop가 없으면, path가 /일때 뿐만아니라, /로 시작하는 모든 URL경로에 매칭된다.
따라서 의도치 않게 Home 컴포넌트가 항상 보여지게 된다.
exact prop을 붙여주면, URL 경로값이 <Ruote>의 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>Users</button>
        </Link>
      </header>
      <hr />
      <main>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/users" component={NotFound} />
      </main>
    </Router>
  )
}

404페이지처리 : Switch 컴포넌트

<Switch> 컴포넌트로 모든 <Route> 컴포넌트를 묶어주면,
그 하위에 있는 <Route> 컴포넌트 중에 매치되는 제일 첫번째 컴포넌트만 보여주고,
이후에 나오는 <Route> 컴포넌트는 매치되더라도 무시한다.
따라서 순서대로 매치되는 URL을 찾게되는데, 이를 활용하여 404페이지 처리를 할 수 있다.

마지막에 path prop이 없는 <Route> 컴포넌트를 하나 추가해주면,
<Route>는 모든 경로에 매치가 가능해지고, 여기에 404 컴포넌트를 할당해줄 수 있다.
그러면, 자연스럽게 위에 나온 <Route> 중에 매치되는 것이 없었을 경우 제일 아래까지 내려올 것이고,
이 마지막 <Route> 컴포넌트가 매치되어 404 페이지가 보여질 것이다.

<main>
  <Switch>
    <Route exact path="/" component={Home} />
    <Route path="/about" component={About} />
    <Route component={NotFound} />
  </Switch>
</main>

참고: Engineering blog by Dale Seo