Woongjae Lee
Daangn - Frontend Core Team ex) NHN Dooray - Frontend Team Leader ex) ProtoPie - Studio Team
React 의 라우팅 이해하기
Dynamic 라우팅
Switch 와 NotFound
JSX 링크로 라우팅 이동하기
Redirect
Lead Software Engineer @ProtoPie
Microsoft MVP
TypeScript Korea User Group Organizer
Marktube (Youtube)
이 웅재
react-router-dom
/
/profile
/about
Client (Browser)
Server
/
/profile
/about
Client (Browser)
브라우저에서 최초에 '/' 경로로 요청을 하면,
React Web App 을 내려줍니다.
내려받은 React App 에서 '/' 경로에 맞는 컴포넌트를 보여줍니다.
React App 에서 다른 페이지로 이동하는 동작을 수행하면,
새로운 경로에 맞는 컴포넌트를 보여줍니다.
npm i react-router-domcra 에 기본 내장된 패키지가 아닙니다.
react-router-dom 은 Facebook 의 공식 패키지는 아닙니다.
가장 대표적인 라우팅 패키지입니다.
'/' => Home 컴포넌트
'/profile' => Profile 컴포넌트
'/about' => About 컴포넌트
// src/pages/Home.jsx
import React from 'react';
export default function Home() {
  return <div>Home 페이지 입니다.</div>;
}// src/pages/Profile.jsx
import React from 'react';
export default function Profile() {
  return <div>Profile 페이지 입니다.</div>;
}// src/pages/About.jsx
import React from 'react';
export default function About() {
  return <div>About 페이지 입니다.</div>;
}// src/App.js
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
function App() {
  return (
    <BrowserRouter>
      <Route path="/" component={Home} />
      <Route path="/profile" component={Profile} />
      <Route path="/about" component={About} />
    </BrowserRouter>
  );
}
export default App;
- Route 컴포넌트에 경로(path) 와 컴포넌트(component) 를 설정하여 나열해줍니다.
- BrowserRouter 로 Route 들을 감싸줍니다.
- 브라우저에서 요청한 경로에 Route 의 path 가 들어있으면 해당 component 를 보여줍니다.<Route path="/" exact component={Home} />import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
function App() {
  return (
    <BrowserRouter>
      <Route path="/" exact component={Home} />
      <Route path="/profile" exact component={Profile} />
      <Route path="/profile/:id" component={Profile} />
      <Route path="/about" component={About} />
    </BrowserRouter>
  );
}
export default App;
<Route path="/profile/:id" component={Profile} />import React from "react";
export default function Profile(props) {
  const id = props.match.params.id;
  console.log(id, typeof id);
  return (
    <div>
      <h2>Profile 페이지 입니다.</h2>
      {id && <p>id 는 {id} 입니다.</p>}
    </div>
  );
}props.match.params.idtypeof id => 'string'
import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
function App() {
  return (
    <BrowserRouter>
      <Route path="/" exact component={Home} />
      <Route path="/profile" exact component={Profile} />
      <Route path="/profile/:id" component={Profile} />
      <Route path="/about" component={About} />
    </BrowserRouter>
  );
}
export default App;
<Route path="/about" component={About} />// src/pages/About.jsx
import React from "react";
export default function About(props) {
  const searchParams = new URLSearchParams(props.location.search);
  const name = searchParams.get("name");
  console.log(name);
  return (
    <div>
      <h2>About 페이지 입니다.</h2>
      {name && <p>name 는 {name} 입니다.</p>}
    </div>
  );
}
new URLSearchParams(props.location.search);// src/pages/About.jsx
import React from "react";
import queryString from "query-string";
export default function About(props) {
  const query = queryString.parse(props.location.search);
  const { name } = query;
  console.log(name);
  return (
    <div>
      <h2>About 페이지 입니다.</h2>
      {name && <p>name 는 {name} 입니다.</p>}
    </div>
  );
}
const query = queryString.parse(props.location.search);여러 Route 중 순서대로 먼저 맞는 하나만 보여줍니다.
exact 를 뺄 수 있는 로직을 만들 수 있습니다.
가장 마지막에 어디 path 에도 맞지 않으면 보여지는 컴포넌트를 설정해서,
	"Not Found" 페이지를 만들 수 있습니다.
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/profile/:id" component={Profile} />
        <Route path="/profile" component={Profile} />
        <Route path="/about" component={About} />
        <Route path="/" component={Home} />
      </Switch>
    </BrowserRouter>
  );
}
export default App;import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/profile/:id" component={Profile} />
        <Route path="/profile" component={Profile} />
        <Route path="/about" component={About} />
        <Route path="/" exact component={Home} />
        <Route component={NotFound} />
      </Switch>
    </BrowserRouter>
  );
}
export default App;<Link to="/">Home</Link><a href="/">Home</a>import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
import Links from "./components/Links";
function App() {
  return (
    <BrowserRouter>
      <Links />
      <Switch>
        <Route path="/profile/:id" component={Profile} />
        <Route path="/profile" component={Profile} />
        <Route path="/about" component={About} />
        <Route path="/" exact component={Home} />
        <Route component={NotFound} />
      </Switch>
    </BrowserRouter>
  );
}
export default App;
import React from 'react';
import { Link } from 'react-router-dom';
function Links() {
  return (
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/profile">Profile</Link>
      </li>
      <li>
        <Link to="/profile/1">Profile/1</Link>
      </li>
      <li>
        <Link to="/about">About</Link>
      </li>
      <li>
        <Link to="/about?name=mark">About?name=mark</Link>
      </li>
    </ul>
  );
}
export default Links;
import { NavLink } from 'react-router-dom';
activeClassName, activeStyle 처럼 active 상태에 대한 스타일 지정이 가능합니다.
Route 의 path 처럼 동작하기 때문에 exact 가 있습니다.
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";
function App() {
  return (
    <BrowserRouter>
      <Links />
      <Switch>
        <Route path="/profile/:id" component={Profile} />
        <Route path="/profile" component={Profile} />
        <Route path="/about" component={About} />
        <Route path="/" exact component={Home} />
        <Route component={NotFound} />
      </Switch>
    </BrowserRouter>
  );
}
export default App;
import React from 'react';
import { NavLink } from 'react-router-dom';
const activeStyle = { color: 'green' };
export default function NavLinks() {
  return (
    <ul>
      <li><NavLink exact to="/" activeStyle={activeStyle}>Home</NavLink></li>
      <li><NavLink exact to="/profile" activeStyle={activeStyle}>Profile</NavLink></li>
      <li><NavLink to="/profile/1" activeStyle={activeStyle}>Profile/1</NavLink></li>
      <li>
        <NavLink
          to="/about"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            if (location.pathname !== '/about') return false;
            const searchParams = new URLSearchParams(location.search);
            return !searchParams.has('name');
          }}
        >
          About
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/about?name=mark"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            if (location.pathname !== '/about') return false;
            const searchParams = new URLSearchParams(location.search);
            return searchParams.has('name');
          }}
        >
          About?name=mark
        </NavLink>
      </li>
    </ul>
  );
}props.history.push("/");// src/pages/Login.jsx
import React from "react";
export default function Login(props) {
  console.log(props);
  function login() {
    setTimeout(() => {
      props.history.push("/");
    }, 1000);
  }
  return (
    <div>
      <h2>Login 페이지 입니다.</h2>
      <button onClick={login}>로그인하기</button>
    </div>
  );
}// src/components/LoginButton.jsx
import React from "react";
export default function LoginButton(props) {
  console.log(props);
  function login() {
    setTimeout(() => {
      props.history.push("/");
    }, 1000);
  }
  return <button onClick={login}>로그인하기</button>;
}
// src/pages/Login.jsx
import React from "react";
import LoginButton from "../components/LoginButton";
export default function Login(props) {
  return (
    <div>
      <h2>Login 페이지 입니다.</h2>
      <LoginButton />
    </div>
  );
}import React from "react";
import { withRouter } from "react-router-dom";
function LoginButton(props) {
  console.log(props);
  function login() {
    setTimeout(() => {
      props.history.push("/");
    }, 1000);
  }
  return <button onClick={login}>로그인하기</button>;
}
export default withRouter(LoginButton);export default withRouter(LoginButton);import { Redirect } from "react-router-dom";
// jsx
<Redirect to="/" />import React from "react";
import {
  BrowserRouter,
  Route,
  Switch,
  Redirect
} from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
import Login from "./pages/Login";
const isLogin = true;
function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/profile/:id" component={Profile} />
        <Route path="/profile" component={Profile} />
        <Route path="/about" component={About} />
        <Route
          path="/login"
          render={() => (isLogin ? <Redirect to="/" /> : <Login />)}
        />
        <Route path="/" component={Home} />
      </Switch>
    </BrowserRouter>
  );
}
export default App;
By Woongjae Lee
Fast Campus Frontend Developer School 17th
Daangn - Frontend Core Team ex) NHN Dooray - Frontend Team Leader ex) ProtoPie - Studio Team