기본 라우팅

React Router 모듈

import { 
  BrowserRouter as Router, 
  // 또는 HashRouter as Router, 
  Switch,
  Route, 
  Link,
  NavLink,
  Redirect
} from 'react-router-dom';

Router 컴포넌트

BrowserRouter 컴포넌트

  • HTML5 History API를 사용해 URL과 매칭되는 UI를 렌더링한다. (예: /lectures)

  • 해시값 없이 pathName을 사용해서 이동한다.

  • IE10+ 부터 사용 가능하다.

HashRouter 컴포넌트

  • URL 해시(#)를 사용해 URL과 UI를 매칭한다. (예: /#/lectures)

  • 검색 엔진이 읽지 못한다.

  • URL 해시를 사용하기 때문에 브라우저나 웹 서버에 제한 없이 사용할 수 있다.

// 예시 
example.com/#/messages/messages
<HashRouter hashType="hashbang">

GitHub Pages에 React 앱을 배포할 경우, HashRouter를 사용해야 한다. 참고 → HashRouter과 BrowserRouter의 차이

라우터 설정

일반적으로 라우터는 App 컴포넌트에 추가한다. 라우터 내부에는 각 라우트 경로와 연결 될 컴포넌트를 설정하고, 각 페이지를 탐색하게 하는 내비게이션으로 구성된다.

const App = () => (
  <Router>
    {/* 내비게이션: <Link>, <NavLink> 사용 */}
    {/* 라우트: <Swtich>, <Router>, <Redirect> 사용 */}
  </Router>
)

또는 ReactDOM 렌더링 과정에서 <Router><App>을 래핑할 수 있다.

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

React Router 컴포넌트 종류

React 웹 앱 제작에 자주 사용되는 컴포넌트

컴포넌트 종류

설명

<BrowserRouter> / <HashRouter>

라우터(Router) 컴포넌트

라우트 경로(Route Path) 매처(matcher) 컴포넌트

라우트를 변경하는 내비게이션(Navigation) 컴포넌트

Route 컴포넌트

Route 컴포넌트는 설정된 path와 매칭되는 컴포넌트를 찾아 일부 UI를 렌더링 한다. 일반적으로 라우트는 path, component 속성을 사용해 표시 할 URL과 컴포넌트를 설정한다.

path / component 속성

path 속성의 값과 매치되는 경로로 이동한다. 이때 path="/" 경우 exact 키워드를 같이 사용해야한다. exact는 정확하게 검사한다는 의미로 이를 설정하지 않으면 /lecture 페이지에서 /(Home) 페이지의 콘텐츠도 같이 보이는 오류가 발생한다.

import Home from './views/Home'
import Lecture from './views/Lecture'
import Lab from './views/Lab'

<BrowserRouter>
  <Route path="/" exact component={Home} />
  <Route path="/lecture" component={Lecture} />
  <Route path="/lab" component={Lab} />
</BrowserRouter>

component 속성을 사용하지 않으면 아래와 같이 작성한다.

<BrowserRouter>
  <Route path="/" exact>
    <Home />
  <Route>
  <Route path="/lecture">
    <Lecture />
  <Route>
  <Route path="/lab">
    <Lab />
  <Route>
</BrowserRouter>

Route 컴포넌트 렌더링 방법

<Route> 컴포넌트를 사용해 렌더링 하는 방법은 다음의 3가지 이다.

렌더링 방법

설명

URL과 매칭되는 컴포너트를 렌더링 한다.

인라인 렌더링 또는 래핑 렌더링 시에 사용한다.

매칭될 경우, 자식 컴포넌트를 렌더링 할 때 사용한다.

component 렌더링

위에서 본 component 속성을 사용해서 렌더링 하는 방식이다.

<Route 
  path="/" 
  component={Home} 
/>

render 함수 렌더링

  • 인라인 렌더링 → render 함수의 반환 값으로 컴포넌트를 내보내는 방식이다. 단, 개발자 도구에서 확인이 불가능하다. (권장 X)

  • render가 전달 받는 인자는 Route 컴포넌트가 전달 받은 props(match, location, history)를 전달 받는다.

// 인라인 렌더링
<Route 
  path="/" 
  exact 
  render={() => <div className="Home">홈</div>} 
/>

// 래핑 렌더링
const FadeInRoute = (({component: Component, ...rest}) => {
  return (
    <Route 
      {...rest}
      // render의 routeProps는 Route컴포넌트에 전달된 ...rest를 전달 받는다.
      render={(routeProps) => (
        <FadeIn>
          <Component {...routeProps} />
        </FadeIn>
      )}
    />
  )
}

<FadeInRoute path="/lab" component={Lab} />

children 함수 렌더링

children 함수 렌더링 방식은 RouteGuard와 같이 애니메이션 라우트를 만들 때 사용할 수 있다. 그래서 path속성을 사용한 일반적인 라우트에서는 사용하지 않는다.

<Route
  children={({ match, ...rest }) => (
    {/* Animate는 항상 렌더링되므로 라이프 사이클 훅을 사용하여 
        자식(child) 컴포넌트를 애니메이션 할 수 있습니다. */}
    <Animate>
      {match && <SubPage {...rest}/>}
    </Animate>
  )}
/>

React에서 애니메이션 기능을 구현하기 위해서 React Spring과 같은 애니메이션 전용 라이브러리를 사용할 수 있다.

Route 컴포넌트의 Props

Route 컴포넌트 props 전달

Route 컴포넌트에 props를 전달 할 때는 render 속성을 사용해서 props를 전달한다.

Categorise 컴포넌트에 sortBy 속성을 전달하기 위해 1번 코드와 같이 작성하면 match, location, history는 Categorise 컴포넌트에 전달 되지 않는다.

/*   1   */
<Route 
  path="/categories" 
  render={(props) => <Categories sortBy="createdAt" />} 
/>

하지만 아래와 같이 컴포넌트에 전달 받은 props를 전개해서 전달해 주면 해당 컴포넌트는 sortBy 속성을 포함한 match, location, history 속성도 모두 전달 받는다.

/*   2   */
<Route 
  path="/categories" 
  render={(props) => <Categories sortBy="createdAt" {...props} />} 
/>

정확한 라우팅 설정

홈 링크 패스 /는 항상 활성화 상태이다. 모든 패스에 /가 있기 때문이다. 그래서 다른 링크를 클릭해도 홈 UI는 항상 표시된다. 홈 링크에 exact 속성을 추가해 정확(exact)하게 패스가 일치할 때만 표시되도록 설정한다.

<NavLive to="/" exact>홈</NavLive>

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

홈 링크를 설정할 땐 항상 exact를 설정하자!

엄격한 경로 구분 설정

strict 속성이 설정된 경우, 현재 URL과 일치하는지 여부를 결정할 때 URL의 후미 슬래시를 고려한다.

<Route path="/one" exact strict>
  <Product />
</Route>

경로

경로 이름

매칭

/one

/one

일치

/one

/one/

불일치

/one

/one/two

불일치

대소문자 구분 설정

경로(path) 이름의 대소문자를 민감하게 구분하고자 한다면 sesitive 속성을 추가한다.

<Route path="/one" sensitive>
  <Product />
</Route>

경로

경로 이름

구분

매칭

/one

/one

true

일치

/One

/one

true

불일치

/One

/one

false

일치

Switch 컴포넌트

자식 컴포넌트 중에 to나 path 값이 일치하면 그 곳에서 멈추고 들어간다.

Route 컴포넌트와 항상 같이 사용한다고 생각하기

<Switch> 
  <Route path="/about" component={About} />
  <Route path="/:user" component={User} />
  <Route path="*" component={NoMatch} />
</Switch>

Link 컴포넌트는 애플리케이션을 탐색하는 기능을 제공한다. to 속성 값으로 경로(path) 문자 값 또는 객체를 설정 할 수 있다. 네비게이션 처럼 클릭 했을 때 해당 패스로 이동하는 링크를 만드는 컴포넌트이다. to값과 일치하는 path로 이동한다.

to 속성에 들어가는 값을 유형

  • string → 간단한 pathName일 때 사용한다.

  • object → 객체 형식으로 path, search 등을 설정할 때 사용한다.

  • function → 중간에 source를 인터챕터(interchapter)하여 설정한다.

to 속성에 객체 형식으로 담에서 보낼 수 있다.

<Link
  to={{
    pathname: "/login",
    search: "?user=hanna&mento=yamoo",
    hash: "#router",
    state: {
      message: "로그인 링크를 통해 전달된 메세지",
      isAuthed: true
    }
  }}
>
  • Link 컴포넌트에 스타일을 줄 수 있다.

  • 일반 Link와 다르게 aria-current 와 calss 속성이 추가 된다.

즉, 활성화 된 상태 클래스 active가 자동으로 설정, 스타일링이 가능하다. Link 컴포넌트를 사용할 예정이라면 NavLink를 사용하는 것이 좋겠다.

innerRef 설정

React 앱(16+)에 React Router 5.1을 사용할 경우, 참조(ref)를 기본으로 <a>에 전달 하므로 forwardRef를 별도로 설정할 필요가 없다. 일반 ref 속성을 사용하면 된다.

<Link
  to="/"
  innerRef={node => {
    // `node`는 마운트 된(mounted) DOM 요소를 참조하고,
    // 마운트가 해제 된 경우(unmount)는 null 입니다.
  }}
/>

<Link
  to="/"
  innerRef={node => { node.addEventListener('click', () => {node.style.color = '#a6cfff'})
  }}
/>
class LinkRefDemo extends React.Component {
  
  anchorRef = React.createRef()

  render() {
    return (
      <Link to="/" innerRef={anchorRef} />
    )
  }

}

정확한 경로에서만 활성화

exact 속성은 경로가 정확히 일치할 때만 활성화 하도록 설정할 때 사용한다. 아래 코드 예시와 같이 exact 속성을 설정해야 /lecture/chapter/* 페이지에서 /lecture 경로의 내비게이션 링크가 활성화 되지 않는다.

<NavLink to="/lecture" exact>강의</NavLink>
<NavLink to="/lecture/chapter/1">1장</NavLink>

Redirect 컴포넌트

여러 개의 Route를 설정 했으나 사용자가 사용자가 입력한 path와 일치하는 Route가 없다면 Redirect 컴포넌트에 설정된 to 속성 값으로 이동한다.

아래의 예시 처럼 Redirect 컴포넌트를 사용할 수 있다. 페이지를 찾을 수 없다는 Route를 만들어 두고 알 수 없는 경로를 입력했을 때 사용자가 해당 페이지로 이동하여 오류임을 알 수 있도록 한다.

사용자 경험을 위해 홈페이지로 이동할 수 있는 링크를 설정해준다.

<Route
  path="/page-not-found"
  render={() => {
    return (
      <div>
        <h1 lang="ko">페이지를 찾을 수 없습니다. 404</h1>
        <ZanzanNavLink to="/">홈 페이지로 돌아가기</ZanzanNavLink>
      </div>
    );
  }}
/>
<Redirect to="/page-not-found" />

from 속성

Redirect의 from 속성의 값을 path로 검색했을 때 to에 설정된 path 값으로 이동한다.

// from : 문자열 설정
// url에 / 입력 시 /home으로 이동 
<Redirect exact from="/" to="/home" />
// url에 /users/:id 입력 시 /users/profile/:id으로 이동 
<Redirect from="/users/:id" to="/users/profile/:id" />

example

// to : 문자열 설정
<Redirect to="/dashboard"/>

// to : 객체 설정
<Redirect to={{
  pathname: '/login',
  search: '?utm=your+file',
  state: {
    referrer: currentLocation
  }
}}/>

// push : 현재 history 항목을 바꾸지 않고, 새 항목 추가
<Redirect to="/dashboard" push />

// from : 문자열 설정
<Redirect from="/admin" to="/dashboard" />
<Redirect from="/users/:id" to="/users/profile/:id" />

// exact : 정확한 URL 매칭 설정
<Redirect exact from="/" to="/home" />

// strict : 엄격한 URL 매칭 설정
<Redirect strict from="/one/" to="/home" />

// sensitive : 대소문자  URL 매칭 설정
<Redirect sesitive from="/One/" to="/one" />

Conclusion

index.js(rootElement)에 라우터 설정 → Browser/HashRouter

import { BrowserRouter as Router } from "react-router-dom";
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Router>
    <App />
  </Router>
);

Last updated