4 분 소요

1. React Routing 이해하기

  • Single Page Application
    • 기존에는 서버로부터 해당 url에 대한 데이터를 받아옴
    • 이제는 서버로부터 하나의 전체 App 받아온 후 클라이언트(Browser)에서 url에 따라서 어떤 것을 보여줄지 결정
  • SPA 라우팅 과정
    1. 브라우저에서 최초에 ‘/’ 경로로 요청
    2. React Web App을 내려줌
    3. 내려받은 React App에서 ‘/’ 경로에 맞는 Component를 보여줌
    4. React App에서 다른 페이지로 이동하는 동작을 수행하면,
    5. 새로운 경로에 맞는 Component를 보여줌
  • cra에 기본 내장된 패키지가 아님
  • react-router-dom은 Facebook의 공식 패키지는 아님
  • 가장 대표적인 라우팅 패키지
# terminal

$ npx create-react-app react-router-example
$ cd react-router-example
$ npm i react-router-dom
$ code .
$ npm start


  • 특정 경로에서 보여줄 component 준비
    • ’/’ => Home Component
    • ‘/profile’ => Profile Component
    • ‘/about’ => About Component
// src/pages/Home.jsx

export default function Home() {
  return <div>Home 페이지</div>;
}

// src/pages/Profile.jsx
export default function Profile() {
  return <div>Profile 페이지</div>;
}

// src/pages/About.jsx
export default function About() {
  return <div>About 페이지</div>;
}


// src/App.js

// Route Component에 path와 component를 설정하여 나열
import { BrowserRouter, Route } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

function App() {
  return (
    // BrowserRouter로 Route를 감싸줌
    // Browser에서 요청한 경로에 Route의 path가 들어있으면 해당 Component를 보여줌
    <BrowserRouter>
      <Route path="/" exact component={Home} />
      <Route path="/profile" component={Profile} />
      <Route path="/about" component={About} />
    </BrowserRouter>
  );
}

export default App;


react-router1

react-router2

react-router3


2. Dynamic Routing

// src/App.js

import { BrowserRouter, Route } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

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;


// src/pages/Profile.jsx

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>
  );
}


react-router4


// src/pages/About.jsx

export default function About(props) {
  const searchParams = props.location.search;
  console.log(searchParams);
  const obj = new URLSearchParams(searchParams);
  console.log(obj.get("name"));
  return <div>About 페이지</div>;
}

// ---------------------------------------------------

import queryString from "query-string";

export default function About(props) {
  const searchParams = props.location.search;
  console.log(searchParams);
  const query = queryString.parse(searchParams);
  console.log(query);
  return (
    <div>
      <h2>About 페이지</h2>
      {query.name && <p>name은 {query.name} 입니다.</p>}
    </div>
  );
}


react-router5


react-router6


3. Switch와 NotFound

  • 여러 Route 중 순서대로 먼저 맞는 하나만 보여줌
  • exact를 뺄 수 있는 로직을 만들 수 있음
  • 가장 마지막에 어디 path에도 맞지 않으면 보여지는 Component를 설정해서, “Not Found” 페이지를 만들 수 있음
// src/App.js

import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
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;


// src/pages/NotFound.jsx

export default function NotFound() {
  return <div>페이지를 찾을 수 없습니다.</div>;
}


react-router4

react-router2

react-router7

react-router1

react-router8


4. JSX 링크로 Routing 이동하기

// src/App.js

import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
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;


// src/components/Links.jsx

import { Link } from "react-router-dom";

export default function Links() {
  return (
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/profile">Profile</Link>
      </li>
      <li>
        <Link to="/profile/LWW">Profile/LWW</Link>
      </li>
      <li>
        <Link to="/about">About</Link>
      </li>
      <li>
        <Link to="/about?name=LWW">About?name=LWW</Link>
      </li>
    </ul>
  );
}


react-router9


  • import { NavLink } from ‘react-router-dom’;
  • activeClassName, activeStyle처럼 active 상태에 대한 스타일 지정 가능
  • Route의 path처럼 동작하기 때문에 exact가 있음
// src/App.js

import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";

function App() {
  return (
    <BrowserRouter>
      <Links />
      <NavLinks />
      <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;


// src/components/NavLinks.jsx

import { NavLink } from "react-router-dom";

const activeStyle = { color: "royalblue" };

export default function NavLinks() {
  return (
    <ul>
      <li>
        <NavLink to="/" exact activeStyle={activeStyle}>
          Home
        </NavLink>
      </li>
      <li>
        <NavLink to="/profile" exact activeStyle={activeStyle}>
          Profile
        </NavLink>
      </li>
      <li>
        <NavLink to="/profile/LWW" activeStyle={activeStyle}>
          Profile/LWW
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/about"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            console.log(match, location);
            return match !== null && location.search === "";
          }}
        >
          About
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/about?name=LWW"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            return match !== null && location.search === "?name=LWW";
          }}
        >
          About?name=LWW
        </NavLink>
      </li>
    </ul>
  );
}


react-router10


5. JS로 Routing 이동하기

// src/App.js

import { BrowserRouter, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";

function App() {
  return (
    <BrowserRouter>
      <Links />
      <NavLinks />
      <Switch>
        <Route path="/login" component={Login} />
        <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;


// src/pages/Login.jsx

import LoginButton from "../components/LoginButton";

export default function Login() {
  return (
    <div>
      <h2>Login 페이지</h2>
      <LoginButton />
    </div>
  );
}


// src/components/LoginButton.jsx

import { withRouter } from "react-router-dom";

export default withRouter(function LoginButton(props) {
  console.log(props);

  function login() {
    setTimeout(() => {
      props.history.push("/");
    }, 1000);
  }

  return <button onClick={login}>로그인하기</button>;
});


react-router11

react-router12


6. Redirect

// src/App.js

import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import Links from "./components/Links";
import NavLinks from "./components/NavLinks";

const isLogin = false;

function App() {
  return (
    <BrowserRouter>
      <Links />
      <NavLinks />
      <Switch>
        <Route
          path="/login"
          render={() => (isLogin ? <Redirect to="/" /> : <Login />)}
        />
        <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;


react-router11

댓글남기기