3 분 소요


SPA와 React Router란?

  • SPA란?

Single Page Application (싱글 페이지 어플리케이션) 의 약자입니다. 말 그대로, 페이지가 1개인 어플리케이션이란 뜻입니다.

기존 전통적인 웹어플리케이션의 구조는 여러 페이지로 구성되어있습니다. 화면이동 시에 화면 이동에 필요한 HTML을 서버사이드에서 받아서 처음부터 다시 로딩하기 때문에 시간이 걸립니다.

SPA는 화면이동 시에 필요한 데이터를 서버사이드에서 HTML으로 전달받지 않고 필요한 데이터만 서버로부터 JSON으로 전달 받아 동적으로 렌더링합니다.

싱글페이지라해서 한 종류의 화면만 있는것은 아닙니다. 예를들어 블로그를 만든다고 예를 들었을때 홈, 포스트 목록, 포스트, 글쓰기 등의 화면이 있습니다. 또한 이 화면에 따라 주소도 만들어줘야 하는데요. 주소가 있어야, 유저들이 북마크도 할 수 있고 서비스에 구글을 통해 유입될 수 있기 때문입니다.

라우팅은 리액트 자체에 내장되어 있지 않기때문에 직접 브라우저 API를 사용해야합니다.

react-router를 이용하여 구현해보겠습니다. 그리고 react-router는 react-native에서도 사용이 가능합니다.


react-router

react-router 라이브러리를 사용하지 않고 라우팅을 했을때 나타나는 문제들이 있습니다.

  • 특정 페이지에 대한 즐겨찾기 등록이 불가합니다. 컴포넌트가 전환되더라도 브라우저 주소창의 URL은 고정되어 있기 때문입니다.

  • 뒤로 가기 버튼을 누르면 해당 앱내에서 이전 페이지로 이동하는 것이 아니라 그 전에 서핑하던 다른 웹사이트로 이동해버립니다.

  • 새로 고침 버튼을 누르면 사용 중이던 컴포넌트가 아닌 무조건 최초에 렌더링되었던 Home 컴포넌트로 이동합니다.

이를 해결하기 위해 react-router를 사용하여 구현해 보겠습니다.


설치

두가지중 취향에 맞게 사용하시면 됩니다.

  • npm i react-router-dom
  • yarn add react-router-dom

router에 내장된 컴포넌트 종류

  • BrowserRouter : URL과 UI를 동기화해주는 라우터이며, 웹 어플리케이션이 History API를 사용하여 페이지를 새로고침 없이 주소 변경이 가능하게 하고, 관련된 정보를 props로 쉽게 조회하거나 이용할 수 있게 해줍니다.

  • Switch - Route로 생성된 자식컴포넌트중 매칭되는 첫번째 Route를 렌더링해줍니다. 보통 메인 Route의 url경로를 “/”로 지정하고 다른 Route에는 “/detail”, “/login” 이런식으로 지정하게 되는데, 만약 Switch를 사용하지 않으면 그냥 메인페이지에 가기 위하여 “/” 경로를 접속했늗네 “/”가 포함된 “/detail”, “/login” 컴포넌트들이 다 렌더링 되는 경우를 보게 됩니다.

  • Route - 컴포넌트에 path 속성을 이용하여 원하는 url를 지정합니다. 그 url에 접속하면 해당 컴포넌트만 렌더링이 됩니다. 즉, 사용자의 경로에 따라 다른 컴포넌트를 보여줄 수 있습니다.

<Router>
  ...
  <Link />
  <Link />
  ...
  <Router />
  <Router />
  ...
</Router>
  • Link - HTML의 <a> 태그와 유사한 기능을 하는 컴포넌트라고 생각하시면 이해가 쉽습니다. <a> 태그는 href 속성을 통해 이동할 경로를 지정하는 반면에 <Link> 컴포넌트는 to prop을 통해서 이동할 경로를 지정해줍니다.
<Link to="/about">About</Link>

예제

먼저 리액트 프로젝트를 만들어줍니다.

  • yarn add create-react-app {app 이름}
  • npx create-react-app {app 이름}

    Home 화면에서 로그인 버튼을 클릭하면 Login 페이지로 넘어가게 구현해 보겠습니다.

  • 프로젝트를 만든후 src/index.js파일에서 다음과 같이 수정합니다.
import { BrowserRouter } from 'react-router-dom';

(... 중략)

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

pages폴더에 파일을 만들어보았습니다. src/pages/Home.js src/pages/About.js

// Home.js
import React from "react";

/**
 * 함수형 컴포넌트 스니펫입니다.
 */
const Home = () => {
  return (
    <div>
      <h1>Home</h1>
      <p> 예제입니다~</p>
    </div>
  );
};

export default Home;

// About.js
import React from "react";

/**
 * 함수형 컴포넌트 스니펫입니다.
 */
const About = () => {
  return (
    <div>
      <h1>About</h1>
      <p>About 예제 입니다~</p>
    </div>
  );
};

export default About;

그리고 App.js과 결과 입니다.

import "./App.css";
import About from "./About";
import Home from "./Home";

function App() {
  return (
    <div className="App">
      <About />
      <Home />
    </div>
  );
}

export default App;

index.js에서 ReactDOM.render()를 썼기 때문에 localhost:3001에는 App.js 컴포넌트가 렌더링이 됩니다. Home, About 컴포넌트를 모두 App의 자식 컴포넌트로 집어넣었기 때문에, 둘 다 출력이 됩니다. 하지만 우리가 원하는 것은 이게 아니기 때문에 localhost:3001에선 Home 컴포넌트가, localhost:3001/about에선 About 컴포넌트가 렌더링 되게 라우팅 해보겠습니다.


route를 이용해 수정해보았습니다.

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

function App() {
  return (
    <div>
      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
    </div>
  );
}

export default App;

위의 App.js에서 Route 컴포넌트가 주소에 따라 다른 화면을 보여주는 라우팅 기능의 컴포넌트이다.

<Route path="/이동할 주소" component={출력할 컴포넌트}/>


/about 으로 이동해보면 페이지가 home과 about이 동시에 나오는걸 볼수있습니다. 이유는 /about에 /가 있기때문입니다. 이 문제는 exact옵션으로 해결할수 있습니다.

<Route path="/이동할 주소" component={출력할 컴포넌트} exact/>

여기서 중요한점은 About쪽이 아닌 Home을 바꿔줘야합니다.

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

다시 about만 표시되는걸 확인할수 있습니다.


link는 <a>와 비슷하다고 위에서 배웠습니다.

<a href="localhost:3000/about"> 간혹 위 코드처럼 사용하면 동일한 결과인지 궁굼해 하시는분들이 있습니다. 하지만 사용하면 안 됩니다. 이유는 route 사용은 현재 페이지에서 상태를 유지하면서 바뀐 주소에 따라 바뀐 화면을 보고싶은 이유입니다. a 태그를 사용하면 상태가 전부 날아가고 기존의 랜더링 컴포넌트를 다 날려보내서 처음부터 렌더링이 진행됩니다.

BrowserRouter를 이용한 다른 무언가를 사용해야 한다. 그게 바로 Link입니다.

<Link to="이동할주소">내용</Link>

대부분의 사이트는 /about을 직접 입력해서 들어가지 않습니다. 로그인 버튼이나 버튼을 만들어 이동하게 됩니다. 이런경우 <Link> 를 사용합니다.

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

function App() {
  return (
    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">어바웃</Link>
        </li>
      </ul>
      <Route path="/" component={Home} exact />
      <Route path="/about" component={About} />
    </div>
  );
}

export default App;

import에 Link를 추가 해줍니다. 홈버튼을 누르면 localhost:3000으로 이동하고 about을 누르면 localhost:3000/about 으로 이동합니다.

댓글남기기