공부블로그

13장. 리액트 라우터로 SPA 개발하기 본문

리액트/리액트를 다루는 기술

13장. 리액트 라우터로 SPA 개발하기

떠어영 2021. 2. 2. 20:33

13. 1 ) SPA란?

SPA란 Single Page Application의 약자로 싱글 페이지 애플리케이션이라는 의미이다.

기존에는 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고, 페이지를 로딩할 때마다 서버에서 리소스를 해석한 뒤 보여준다. 하지만 이런 방식은 성능상의 문제가 발생할 수 있다.

그래서 최근에는 리액트 같은 라이브러리 혹은 프레임워크를 사용하여 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고, 우선 애플리케이션을 브라우저에 불러와서 실행시킨 후에 사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트해준다. 

SPA의 경우, 서버에서 사용자에게 제공하는 페이지는 한 종류이지만 해당 페이지에서 로딩된 자바스크립트와 현재 사용자 브라우저 주소 상태에 따라 다양한 화면을 보여줄 수 있다. 이때 다른 주소에 다른 화면을 보여주는 것을 라우팅이라고 한다.

 

13. 2 ) 사용법

13. 2. 1 ) 프로젝트 생성 & 라이브러리 설치

 

$ yarn create react-app router-tutorial

 

$cd router-tutorial

$yarn add react-router-dom  // 라이브러리 설치

 

 

13. 2. 2 ) 프로젝트에 라우터 적용

 

scr/index.js 파일에서 react-router-dom에 내장되어 있는 BrowserRouter라는 컴포넌트를 사용하여 감싸준다.

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
//프로젝트에 리액트 라우터를 적용
//웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경하고,
//현재 주소에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 해준다.
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);

 

13. 2. 3 ) 페이지 만들기

 

Home. js

import React from "react";

const Home = () => {
  return (
    <div>
      <h1>홈</h1>
      <p>홈, 그 페이지는 가장 먼저 보여주는 페이지</p>
    </div>
  );
};
export default Home;

About. js

import React from "react";

const About = () => {
  return (
    <div>
      <h1>소개</h1>
      <p>이 프로젝트는 리액트 라우터 기초를 실습해 보는 예제 프로젝트입니다.</p>
    </div>
  );
};
export default About;

 

13. 2. 4 ) Route 컴포넌트로 특정 주소에 컴포넌트 연결

 

사용방식: <Route path="주소규칙" component={보여 줄 컴포넌트} />

 

App. js

//Route라는 컴포넌트를 사용해서 사용자의 현재 경로에 따라 다른 컴포넌트를 보여준다.
// <Route path="주소규칙" component={보여 줄 컴포넌트} />

import React from "react";
import { Route } from "react-router-dom";
import About from "./About";
import Home from "./Home";

const App = () => {
  return (
    <div>
      <Route
        path="/"
        component={Home}
        exact={true} //exact라는 props를 true로 설정
      />
      <Route path="/about" component={About} />
    </div>
  );
};
export default App;

이렇게 하면 yarn start를 했을 때, 첫 화면으로는 Home이 나오고, 주소창에 http://localhost:3000/about 경로를 입력하면 About컴포넌트가 나온다.

 

 

13. 2. 5 ) Link 컴포넌트를 사용하여 다른 주소로 이동하기

 

Link 컴포넌트는 클릭하면 다른 주소로 이동시켜주는 컴포넌트이다. 일반 웹 애플리케이션에서는 a태그를 사용하여  페이지를 전환하는데, 이 태그는 처음부터 렌더링하게 되기 때문에 직접 사용하지 않고 HTML5 History API를 사용하여 페이지의 주소만 변경해준다. 이렇게 하면 컴포넌트 자체는 a태그로 이루어져 있지만 페이지 전환을 방지하는 기능이 내장되어 있다.

 

사용방식: <Link to='주소'>내용</Link>

 

App. js

//Route라는 컴포넌트를 사용해서 사용자의 현재 경로에 따라 다른 컴포넌트를 보여준다.
import React from "react";
import { Route, Link } from "react-router-dom";
import About from "./About";
import Home from "./Home";

const App = () => {
  return (
    <div>
      <u1>
        <li>
          <Link to="/">홈</Link>
        </li>
        <li>
          <Link to="/about">소개</Link>
        </li>
      </u1>
      <hr />
      <Route
        path="/"
        component={Home}
        exact={true} //exact라는 props를 true로 설정
      />
      <Route path="/about" component={About} />
    </div>
  );
};
export default App;

 

( 실행 화면 )

 

13. 3 ) Route 하나에 여러 개의 path 설정하기

사용방법: < Route path={ ["/about""/info"] } component={About} />

이렇게 설정하면 http://localhost:3000/about  http://localhost:3000/info에서 같은 페이지를 보여줄 수 있다.

 

13. 4 ) URL 파라미터와 쿼리

페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야 할 때도 있다. 이는 파라미터와 쿼리로 나눌 수 있다.

  • 파라미터 예시: /profile/velopert
  • 쿼리 예시: /about?details=true

일반적으로 파라미터는 특정 아이디 혹은 이름을 사용하여 조회할 때 사용하고 쿼리는 어떤 키워드를 검색하거나 페이지에 필요한 옵션을 전달할 때 사용한다.

 

 

13. 4. 1 ) URL 파라미터

 

뒷부분에 유동적인 username 값을 넣어줄 때 해당 값을 props로 받아 와서 조회하는 방법

 

Profile. js

import React from "react";

const data = {
  velopert: {
    name: "김민준",
    description: "리액트를 좋아하는 개발자",
  },
  gildong: {
    name: "홍길동",
    description: "고정 소설 홍길동전의 주인공",
  },
};

const Profile = ({ match }) => {
  const { username } = match.params; 
  //라우트로 사용되는 컴포넌트에서 받아 오는 match라는 객체 안의 params값을 참조
  //match객체 안에는 현재 컴포넌트가 어떤 경로 규칙에 의해 보이는지에 대한 정보가 있다.
  const Profile = data[username];  //data[velopert] or data[gildong]
  if (!Profile) {
    return <div>존재하지 않는 사용자입니다.</div>;
  }
  return (
    <div>
      <h3>
        {username} ({Profile.name})
      </h3>
      <p>{Profile.description}</p>
    </div>
  );
};

export default Profile;

 

App. js 에서 아래코드 추가

...
        <li>
          <Link to="/profile/velopert">velopert 프로필</Link>
        </li>
        <li>
          <Link to="/profile/gildong">gildong 프로필</Link>
        </li>
      </ul>
      <hr />
     ...
      <Route path="/profile/:username" component={Profile} />
    </div>
  );
};
export default App;

 

13. 4. 2 ) URL 쿼리

 

쿼리는 location 객체에 들어있는 search값에서 조회할 수 있다.

location 객체는 라우트로 사용된 컴포넌트에게 props로 전달되며, 웹 애플리케이션의 현재주소에 대한 정보를 지니고 있다.

http:// localhost:3000/ about? detail=true 주소로 들어갈 때

location객체는  { "pathname": "/about" , "search": "?detail=true" , "hash: " " " } 이다. URL쿼리를 읽을 때는 serach 값을 확인해야 한다. ( 문자열에 여러가지값을 설정해 줄 수 있다, 객체형태로 변환 )

 

About. js

import React from "react";
import qs from "qs";

const App = ({ location }) => {
  const query = qs.parse(location.search, {
    ignoreQueryPrefix: true, //이 설정을 통해 문자열 맨 앞의 ?를 생략
  });
  const showDetail = query.detail === "true"; //쿼리의 파싱 결과값은 문자열이다.
  return (
    <div>
      <h1>소개</h1>
      <p>이 프로젝트는 리액트 라우터 기초를 실습해 보는 예제 프로젝트입니다.</p>
      {showDetail && <p>detail값을 true로 설정하셨군요!</p>}
    </div>
  );
};
export default App;

 

 

13. 5 ) 서브 라우트

라우트 내부에 또 라우트를 정의하는 것. 라우트로 사용되고 있는 컴포넌트 내부에 Route 컴포넌트를 또 사용하면 된다.

 

Profiles. js

import React from "react";
import { Link, Route } from "react-router-dom";
import Profile from "./Profile";

const Profiles = () => {
  return (
    <div>
      <h3>사용자 목록</h3>
      <ul>
        <li>
          <Link to="/profiles/velopert">velopert</Link>
        </li>
        <li>
          <Link to="/profiles/gildong">gildong</Link>
        </li>
      </ul>
      <Route
        path="/profiles"
        exact //exact = {true}와 같다.
        render={() => <div>사용자를 선택해 주세요.</div>}
        // component 대신 render를 넣어줌 -> 컴포넌트 자체를 전달하는 것이 아니라 보여주고 싶은 JSX를 넣어줌
        //따로 컴포넌트를 만들기 애매하거나 컴포넌트에 props를 별도로 넣어주고 싶을 떄 사용
      />
      <Route path="/profiles/:username" component={Profile} />
    </div>
  );
};
export default Profiles;

App. js

//Route라는 컴포넌트를 사용해서 사용자의 현재 경로에 따라 다른 컴포넌트를 보여준다.
// <Route path="주소규칙" component={보여 줄 컴포넌트} />
// <Link to='주소'>내용</Link>

import React from "react";
import { Route, Link } from "react-router-dom";
import About from "./About";
import Home from "./Home";
import Profiles from "./Profiles";

const App = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/">홈</Link>
        </li>
        <li>
          <Link to="/about">소개</Link>
        </li>
        <li>
          <Link to="/profiles">프로필</Link>
        </li>
      </ul>
      <hr />
      <Route path="/" component={Home} exact={true} />
      <Route path={["/about", "/info"]} component={About} />
      <Route path="/profiles" component={Profiles} />
    </div>
  );
};
export default App;

 

13. 6 ) 리액트 라우터 부가 기능

13. 6. 1 ) history 

 

history는 라우트로 사용된 컴포넌트에 match, location고 함께 전달되는 props중 하나로, 이 객체를 통해 컴포넌트 내에 구현하는 메서드에서 라우터 API를 호출할 수 있다.

예를 들어 버튼을 눌렀을 때 뒤로 가기나, 로그인 후 화면을 전환하거나, 다른 페이지를 이탈하는 것을 방지할 때 활용한다. ( HistorySample. js )

 

13. 6. 2 ) withRouter

 

withRouter 함수는 Hoc( Higher-order Component )이다. 라우트로 사용된 컴포넌트가 아니어도 match, location, history 객체를 접근할 수 있다. 

WithRouterSample에서 props로 가져온 match, location, history를 JSON으로 stringfy해준다. 그리고 이 컴포넌트를 Profiles에 렌더링한다.

그런데 여기서 match객체의 params가 비어있는데 이는 Profiles에서 username파라미터를 읽어 오지 못하기 때문이다. 따라서 Profile 컴포넌트에 WithRouterSample을 넣어주면 params. username을 잘 보여준다.

 

 

13. 6. 3 ) Switch

 

Switch 컴포넌트는 여러 Route를 감싸서 그중에 일치하는 단 하나의 라우트만을 렌더링시켜준다. 이를 사용하면 모든 규칙과 일치하지 않을 때 보여줄 Not Found 페이지도 구현할 수 있다.

 

 

13. 6. 4 ) NavLink

 

NavLink는 Link와 비슷하다. 현재경로와 Link에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 CSS클래스를 적용할 수 있는 컴포넌트이다.

NavLink에서 링크가 활성화되었을 때의 스타일을 적용할 때는 activeStyle 값을, CSS클래스를 적용할 때는 activeClassName 값을 props로 넣어준다.

 

 

이번 장에서는 리액트 라우터를 사용하여 주소 경로에 따로 다양한 페이지를 보여 주는 방법을 알아보았다.