본문 바로가기
웹 프론트엔드/React 리액트 (기초)

[React] 라우터(Router), 스위치(Switch), 링크(Link), 리다이렉트(Redirect)를 이용한 페이지 이동

by 지구인한군 2020. 10. 28.

 이때까지의 예제 및 실습에서는 페이지(URL) 이동이 없었습니다. 그래서 이번에는 페이지 이동 관련 기능들을 모아서 

정리하겠습니다. 일단 리액트의 페이지 이동은 기존 서버 사이드 랜더링 기술과 개념이 조금 다릅니다. 쉽게 말씀드리면

리액트는 서버가 아닌 클라이언트에서 웹 문서를 생성합니다. 이를 SPA(Single Page Application)라고도 합니다. 그럼

이론은 너무 어려우니(무책임) 바로 실습 가겠습니다. URL을 다루기 때문에 스토리북이 아닌 App.js에 직접 넣겠습니다.

 

먼저 명령 프롬프트에서 리액트 라우터를 추가합니다.

> yarn add react-router-dom

 

// ..\test_project\src\App.js

import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import MainPage from "./components/MainPage";
import SubPage from "./components/SubPage";
import NotPage from "./components/NotPage";

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route path="/" exact render={() => <MainPage />} />
          <Route path="/subpage" exact component={SubPage} />
          <Route path="*" render={ props => <NotPage url={props.match.url} />} />
        </Switch>
      </Router>
    );
  }
}

export default App;

 

 위에서 설명했듯이 리액트는 페이지(URL) 이동할 때마다 서버에서 받는 것이 아니라 자바스크립트가 출력을 해줍니다.

페이지 경로를 나눠주는 것이 라우터입니다. 라우터에도 여러 종류가 있지만 이번에는 브라우저의 주소를 감지하는

BrowserRouter를 다루겠습니다. <Router>의 자식인 <Route>가 하나하나의 페이지입니다. 세 개의 페이지가 있으며

path가 주소, exact 옵션은 주소가 일치하는지, 다음은 넘어갈 컴포넌트와의 연결입니다. 또 밑에서 설명드리겠습니다.

마지막으로 <Switch>는 자식들 중에 처음으로 조건이 만족하는 하나의 페이지(컴포넌트)만 출력하도록 합니다.

 

// ..\test_project\src\components\MainPage.jsx

import React, { PureComponent } from "react";
import { Link } from "react-router-dom";

class MainPage extends PureComponent {
  render() {
    const imgSrc =
      "https://www.google.co.kr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
    return (
      <div>
        <img src={imgSrc} alt="google" />
        <Link to="/subpage">
          <p>서브 페이지 이동</p>
        </Link>
      </div>
    );
  }
}

export default MainPage;

 

<Route path="/" ...> http://localhost:3000/ 루트인 메인 페이지입니다. 구글 이미지 하나와 서브 페이지

이동 링크가 있습니다. <Link>는 <a> 태그처럼 링크를 걸어주지만 URL 개념 하고는 다른 path 개념입니다.

 

// ..\test_project\src\components\SubPage.jsx

import React, { PureComponent } from "react";
import { Redirect } from "react-router-dom";

class SubPage extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isBack: false,
    };
  }
  render() {
    console.log("this.props : ", this.props);
    const { match, location, history } = this.props;
    return (
      <React.Fragment>
        <p>match.isExact : {String(match.isExact)}</p>
        <p>match.path : {match.path}</p>
        <p>match.url : {match.url}</p>
        <p>location.key : {location.key}</p>
        <p>location.pathname : {location.pathname}</p>
        <p>history.action : {history.action}</p>
        <button onClick={() => this.setState({ isBack: true })}>
          메인 페이지 이동
        </button>
        {this.state.isBack && <Redirect to="/" />}
      </React.Fragment>
    );
  }
}

export default SubPage;

 

<Route path="/subpage" ...> http://localhost:3000/subpage 서브 페이지입니다. App.js의 <Route> 부분이

render={...}가 아닌 component={SubPage}로 되어 있는데, 이런 식으로 연결하면 match, location, history

프로퍼티를 전달받아 사용할 수 있습니다. 메인 이동은 <Redirect>를 사용해 조건이 맞으면 바로 이동이 가능합니다.

 

// ..\test_project\src\components\NotPage.jsx

import React, { PureComponent } from "react";
import { Link } from "react-router-dom";

class NotPage extends PureComponent {
  render() {
    const url = this.props.url;
    return (
      <React.Fragment>
        <p>{url}는 없는 페이지입니다.</p>
        <Link to="/">메인으로 돌아가기</Link>
      </React.Fragment>
    );
  }
}

export default NotPage;

 

<Route path="*" ...> http://localhost:3000/* 에러 페이지입니다. *표현이 정규식의 모든 문자이기 때문에 메인과

서브 페이지를 제외한 모든 페이지를 없는 페이지로 판별합니다. 부모에게 url 프로퍼티를 받아 화면에 출력합니다.

 

 이렇듯 상위에서 라우터, 스위치를 설정해 놓으면 링크나 리다이렉트를 사용해 자유로운 페이지 이동이 가능합니다.

또한 브라우저 주소창 URL 직접 입력도 라우터가 감지해 주므로 에러 페이지 처리도 쉽게 할 수 있습니다.

 

이론은 어려워도 실습은 참 쉽죠?

댓글