본문 바로가기

Frontend/React

2021-04-23 :: 리액트 라우터로 SPA 개발하기

SPA란?

SPA는 Single Page Application의 약어이다. 말 그대로 한 개의 페이지로 이루어진 어플리케이션이라는 뜻을 가지고 있다. 전통적인 웹 페이지에는 다음과 같이 여러 페이지로 구성되어 있다. 기존에는 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아 왔다.

 

요즘은 웹에서 제공되는 정보가 정말 많기 때문에 기존처럼 서버 측에서 모든 뷰를 준비한다면 성능상의 문제가 발생할 수 있다. 그래서 리액트 같은 라이브러리를 사용해 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고, 새로운 데이터가 필요한 경우에만 서버 API를 호출하여 로드한다.

 

리액트 라우팅 라이브러리로는 리액트 라우터, 리치 라우터, Next.js등이 있다.

SPA의 단점

SPA의 단점은 앱의 규모가 커지면 자바스크립트 파일이 너무 커진다는 것이다. 사용자가 방문하지 않는 페이지 역시 스크립트로 불러오기 때문이다. 하지만 이 문제는 코드 스플리팅을 사용하여 해결 가능하다. 다른 문제는 자바스크립트를 실행하지 않는 일반 크롤러에서는 페이지의 정보를 제대로 수집하기 힘들다는 것이다. 

프로젝트 준비 및 기본적인 사용법

리액트 라우터를 설치할 때는 터미널에 다음 코드를 입력 해주면 된다.

$ yarn add react-router-dom

프로젝트에 리액트 라우터를 적용할 때는 src/index.js 파일에서 react-router-dom에 내장되어 있는 BrowserRouter라는 컴포넌트를 사용하여 감싸면 된다. 이 컴포넌트는 웹 어플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경하고, 현재 주소에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 합니다.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {BrowserRouter} from 'react-router-dom';

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

Route 컴포넌트로 특정 주소에 컴포넌트 연결

Route 컴포넌트를 사용하면 어떤 규칙을 가진 경로에 어떤 컴포넌트를 보여 줄지 정의할 수 있다. 사용 방식은 다음과 같다.

<Route path="주소규칙" component={보여 줄 컴포넌트} />
import React from 'react';
import {Route} from 'react-router-dom';
import Home from './Home';
import About from './About';

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

export default App;

/about 경로로 들어가면 About 컴포넌트만 나오기를 기대했지만, 예상과 다르게 두 컴포넌트가 모두 나타났다. /about 경로가 /규칙에도 일치하기 때문에 발생한 현상이다. 이를 수정하기 위해 Home을 위한 Route 컴포넌트에 exact라는 props을 true로 설정한다.

<Route path="/" component={Home} exact={true}/>

Link 컴포넌트를 사용하여 다른 주소로 이동하기

Link 컴포넌트는 클릭하면 다른 주소로 이동시켜 주는 컴포넌트이다. 일반 웹 어플리케이션에서는 a 태그를 사용하여 페이지를 전환한다. 하지만 이 태그는 페이지를 전환하는 과정에서 페이지를 새로 불러오기 때문에 어플리케이션이 들고 있던 상태들을 모두 날려 버리게 된다.

Link 컴포넌트를 사용하여 페이지를 전환하면, 페이지를 새로 불러오지 않고 어플리케이션은 그대로 유지한 상태에서 HTML5 History API를 사용해 페이지의 주소만 변경해 준다.

Route 하나에 여러 개의 path 설정하기

Route 하나에 여러 개의 path를 지정하는 것은 최신 버전의 리액트 라우터 v5부터 적용된 기능이다.

과거에 다음과 같이 작성해야 했던 코드는

<Route path="/about" component={About}/>
<Route path="/info" component={About}/>

이제 다음과 같이 한 줄로 작성할 수 있다.

<Route path={['/about', '/info']} component={About}/>

URL 파라미터와 쿼리

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

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

유동적인 값을 사용해야 하는 상황에서 파라미터를 써야 할지 쿼리를 써야 할지 정할 때, 무조건 따라야 하는 규칙은 없다. 하지만 일반적으로 파라미터는 특정 아이디 혹은 이름을 사용하여 조회할 때 사용하고, 쿼리는 우리가 어떤 키워드를 검색하거나 페이지에 필요한 옵션을 전달할 때 사용한다.

URL 파라미터

profile 페이지에서 파라미터를 사용해 보자. /profile/seyoung8239와 같은 형식으로 뒷부분에 유동적인 username 값을 넣어 줄 때 해당 값을 props로 받아 와서 조회하는 방법을 알아보자. 

<Route path='/profile/:username' component={Profile}/>
import React from 'react';

const data = {
   seyoung8239: {
      name: '박세영',
      description: '개발자'
   },
   asdf: {
      name: '만두',
      description: '바보'
   }
};

const Profile =({match}) => {
   const {username} = match.params; //destruction allocation?
   const profile = data[username];
   if(!profile) return <div>존재하지 않는 사용자입니다.</div>;
   return(
      <div>
         <h3>
            {username}({profile.name})
         </h3>
         <p>{profile.description}</p>
      </div>
   );
};

export default Profile;

URL 파라미터를 사용할 때는 라우트로 사용되는 컴포넌트에서 받아오는 match라는 객체 안의 params 값을 참조한다. 또한 라우트를 정의할 때 path 규칙에는 /profiles/:username이라고 넣어 주면 된다. 이렇게 설정하면 match.params.username 값을 통해 현재 username 값을 조회할 수 있다.