[velog 클론 코딩 개발기 -2 ] 페이지 라우팅

Yeojin Choi·2021년 11월 1일
0

velog 클론코딩

목록 보기
2/5

안녕하세요!
이번주는 velog 클론코딩 프로젝트를 위한 개발 환경 셋팅을 (대충) 마무리하였습니다.

3명이서 프로젝트를 진행하기 때문에, 코드 충돌을 방지하고 각자의 기능 개발을 편리하게 하기 위해서 페이지를 나누고자 하였습니다. react-router-dom 패키지를 사용해 페이지 라우팅 기능을 공부하고, 간단하게 구현한 내용을 정리해보았습니다.

1. react-router-dom 사용하기

SPA는 초기 요청 시 서버에서 첫 페이지를 처리하고, 이후 라우팅은 클라이언트에서 처리하는 웹 어플리케이션 입니다.

페이지 전환에 의한 렌더링을 클라이언트에서 처리하기 위해 react-router-dom 패키지를 설치하고, 사용해보겠습니다.

npm i -D react-router-dom

react-router-dom 에서 제공하는 컴포넌트를 사용해 기능을 구현할 것인데요, 먼저 react-router-dom 에서 어떤 컴포넌트를 제공하는지 알아보겠습니다.

  • BrowserRouter : 페이지 라우팅 기능이 제공될 컴포넌트 전체를 BrowserRouter 컴포넌트로 감싸야 합니다. react 개발자 도구로 확인해보니, BrowserRouter - Router - Router.Provider - Router-History.Provider 컴포넌트가 생성되네요! 브라우저 히스토리 API를 사용하기 위한 Context 를 제공하나봅니다.
  • Link : 클릭 이벤트를 통해 페이지를 전환하고자 할때는 Link 컴포넌트로 감싸야합니다. href 를 사용하면 새로고침을 해버리기 때문에, 이 컴포넌트를 사용해서 새로고침을 막고 페이지 기능을 구현해야합니다.
    - to : 이동할 url ex) localhost:3000/write
  • Route : 각 페이지를 정의하기 위한 컴포넌트 및 url 를 설정합니다.
    - exact : 주어진 path와 완벽히 일치했을 때만 해당 컴포넌트를 렌더링하라고 설정해주는 속성입니다. exact 속성을 주지 않는다면 url 로 시작하는 모든 컴포넌트를 렌더링해버립니다. 즉, localhost:3000/abc 로 지정된 컴포넌트를 렌더링하라고 했는데 localhost:3000/abcd, localhost:3000.abcde 로 지정된 컴포넌트도 렌더링하게 됩니다.
    - component : 현재 주소가 path로 시작했을때 렌더링해야하는 컴포넌트를 전달해줍니다.
  • Switch : Switch 컴포넌트로 감싼 Route 컴포넌트들 중 매칭되는 첫번째 컴포넌트만 렌더링해주는 역할을 합니다.

//App.tsx
import React from 'react';
import { BrowserRouter, Route, Link, Switch } from 'react-router-dom';
import VelogPage from './pages/velog/VelogPage';
import ReadingListPage from './pages/readingList/ReadingListPage';
import RecentPage from './pages/home/RecentPage';
import SavesPage from './pages/SavesPage';
import SettingPage from './pages/SettingPage';
import WritePage from './pages/home/PostPage';
import HomePage from './pages/home/HomePage';

const App = () => {
  const userId = "yeojin";
  return (
    <>
      <h3>bevelog</h3>
      <BrowserRouter>
        <ul>
          <li>
            <Link to="/">트렌딩</Link>
          </li>
          <li>
            <Link to="/recent">최신</Link>
          </li>
          <li>
            <Link to="/write">새 글 작성</Link>
          </li>
          <li>
            <Link to={`/@${userId}`}>MyVelog</Link>
          </li>
          <li>
            <Link to="/saves">임시 글</Link>
          </li>
          <li>
            <Link to="/lists">읽기 목록</Link>
          </li>
          <li>
            <Link to="/setting">설정</Link>
          </li>      
	<Switch>
            <Route path="/@:userId" component={VelogPage} />
            <Route path="/recent" component={RecentPage} />
            <Route path="/write" component={WritePage} />
            <Route path="/saves" component={SavesPage} />
            <Route path="/lists" component={ReadingListPage} />
            <Route path="/setting" component={SettingPage} />
          </Switch>
        </ul>
      </BrowserRouter>
    </>
  );
};

export default App;

App.tsx 에서 li 요소를 클릭하면 해당하는 컴포넌트가 렌더링됩니다.
MyVelog 요소를 클릭하면 이동할 path 를 /@${userId}, Route 의 path 또한 /@:userId 로 지정해주었습니다. 이렇게 지정해 준 이유는 라우트 컴포넌트에 userId 를 params 로 전달해주기 위해서 입니다.

라우트 컴포넌트로 설정된 컴포넌트는 RouteComponentProps type의 props 를 전달받게 되는데, 이를 이용해 params 또는 query 를 사용해 라우트 컴포넌트에 값을 전달해 줄 수 있습니다.

  • history : go, goBack, push 등을 사용해 페이지를 전환할 수 있습니다.
  • location : 현재 경로 정보, url 쿼리(/abc?foo=bar 형태) 등의 정보를 가지고 있습니다.
  • match : 어떤 라우트에 매치되었는지의 정보, params 정보 (/abc/:userId 형태) 를 가지고 있습니다.

query 로 전달하려면, query를 해석하는 라이브러리(query-string)를 설치해야하기 때문에 params 를 전달하는 방법을 사용하겠습니다.

import React from 'react';
import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom';
import UserPage from './UserPage';
import ArticlePage from './ArticlePage';
import SeriesPage from './SeriesPage';

const VelogPage = ({ match }: RouteComponentProps) => {
  const userId = match.params.userId;
  return (
    <div>
      {`내 벨로그 페이지 입니다. userId : ${userId}`} //(1)
      <br />
      <ul>
        <li>
          <Link to={`${match.url}`}></Link> //(2)
        </li>
        <li>
          <Link to={`${match.url}/series`}>시리즈</Link>
        </li>
        <li>
          <Link to={`${match.url}/about`}>소개</Link>
        </li>
      </ul>
	//(3)
        <Route exact path={match.url} component={ArticlePage} />
      <Switch>
        <Route path={`${match.url}/series`} component={SeriesPage} />
        <Route path={`${match.url}/about`} component={UserPage} />
      </Switch>
    </div>);
};

export default VelogPage;

(1) App.tsx 에서 userId 라는 param 을 만들었기 때문에 match.params.userId 를 통해 값을 조회할 수 있습니다.

(2) match 객체의 url 속성으로 현재 url을 알아낼 수 있습니다.

(3) 내 벨로그 페이지도 글 / 시리즈 / 소개 페이지로 이루어져 있기 때문에 라우트로 설정된 컴포넌트 내부에서 라우트를 설정해주었습니다.

쨘!

❗️❗️❗️
@ 를 붙인 이유는 @를 안붙였더니 사용자의 id 로 url 을 지정해주고 싶었는데, (localhost:3000/yeojin 처럼) /뒤에 입력한 값이 parameter 로 지정이 되어버린건지 페이지 이동을 안하고 parameter가 되어버렸습니다... 그래서 velog 처럼 @ 를 붙였더니 잘 작동을 하네요!!

profile
프론트가 좋아요

0개의 댓글