본문 바로가기

리액트

리액트 라우터

기본적으로 우리 팀이 관리하는 프로젝트는 MPA(Multi-Page-Application) 구조를 가지고 있다.

MPA란, 각각의 Page URL을 통해 그에 맞는 HTML을 불러와서 보여주는 형식을 말한다.

 

React를 도입하게 되면서 React는 기본적으로 SPA(Single-Page-Application)을 취하고 있기 때문에 그에 맞는 라우팅을 설정해주어야 한다.

즉, SPA는 CSR(Client-Side-Routing)을 취하고 있기 때문에 하나의 HTML 파일에서 모든 라우팅을 다 처리한다는 의미이다.

 

History and Locations

React Router가 어떠한 라우팅 작업이든 할 수 있으려면 브라우저의 History Stack의 변경 사항을 구독할 수 있어야 한다.

브라우저는 사용자가 웹사이트를 탐색 시 고유한 기록 스택을 유지하는데, 이를 통해서 뒤로가기, 앞으로 가기 버튼이 동작한다.

즉, 브라우저는 사용자가 링크를 클릭하거나 양식을 제출하거나, 뒤로 및 앞으로 가기를 클릭할 때마다 서버에 요청을 보낸다.

 

  1. clicks a link to /dashboard
  2. clicks a link to /accounts
  3. clicks a link to /cutomer/123
  4. clicks the back button
  5. clicks a link to /dashboard

 

위 순서대로 진행 시 히스토리 스택은 다음과 같이 변경된다(진한 URL이 현재 URL)

  1. ['/dashboard']
  2. ['/dashboard', '/accounts']
  3. ['/dashboard', '/accounts', '/customer/123']
  4. ['/dashboard', '/accounts', '/customer/123']
  5. ['/dashboard', '/accounts', '/dashboard']

 

 

History Object

CSR을 통해 개발자는 브라우저 History Stack을 조작할 수 있다.

즉, 서버에 요청하는 브라우저의 기본 동작 없이 URL을 변경하기 위해 다음과 같은 코드를 작성할 수 있다.

<a
  href="/contact"
  onClick={(event) => {
    // stop the browser from changing the URL and requesting the new document
    event.preventDefault();
    // push an entry into the browser history stack and change the URL
    window.history.pushState({}, undefined, "/contact");
  }}
/>

그러나 위와 같은 코드는 URL을 리스닝하지 않는다.(POP 이벤트는 구독할 수 있다!)

즉, URL에 대한 변경 사항을 클라이언트에서 구독하지 않는다는 것이다.

 

여기에서 React Router의 History 객체가 작동하게 되는데, History 액션이 PUSH, POP, REPLACE인지 여부에 따라 "URL 리스닝"변경 방법을 제공한다.

 

let history = createBrowserHistory();
history.listen(({ location, action }) => {
  // this is called whenever new locations come in
  // the action is POP, PUSH, or REPLACE
});

즉, 사용자 자체적으로 히스토리 객체를 설정할 필요가 없다는 말이다.

 

이것이 <Router>의 역할인데, 히스토리 객체 하나를 설정하고, 히스토리 스택의 변경사항을 구독하여 URL이 변경되면 상태를 업데이트를 하고 그에 따른 UI를 렌더링하게 된다.

 

 

Routes

<Routes>는 porps.children을 재귀하며 props를 제거하고 라우트 객체를 생성한다.

<Routes>
  <Route path="/" element={<App />}>
    <Route index element={<Home />} />
    <Route path="teams" element={<Teams />}>
      <Route path=":teamId" element={<Team />} />
      <Route path=":teamId/edit" element={<EditTeam />} />
      <Route path="new" element={<NewTeamForm />} />
      <Route index element={<LeagueStandings />} />
    </Route>
  </Route>
  <Route element={<PageLayout />}>
    <Route path="/privacy" element={<Privacy />} />
    <Route path="/tos" element={<Tos />} />
  </Route>
  <Route path="contact-us" element={<Contact />} />
</Routes>

위와 같은 route tree 컴포넌트 들을

let routes = [
  {
    element: <App />,
    path: "/",
    children: [
      {
        index: true,
        element: <Home />,
      },
      {
        path: "teams",
        element: <Teams />,
        children: [
          {
            index: true,
            element: <LeagueStandings />,
          },
          {
            path: ":teamId",
            element: <Team />,
          },
          {
            path: ":teamId/edit",
            element: <EditTeam />,
          },
          {
            path: "new",
            element: <NewTeamForm />,
          },
        ],
      },
    ],
  },
  {
    element: <PageLayout />,
    children: [
      {
        element: <Privacy />,
        path: "/privacy",
      },
      {
        element: <Tos />,
        path: "/tos",
      },
    ],
  },
  {
    element: <Contact />,
    path: "/contact-us",
  },
];

위와 같이 만들어주는 것이 <Routes> 컴포넌트의 역할이다.

 

 

한줄 요약

react router는 SPA인 React에서 Routing을 처리해주는 라이브러리이며, 내부적으로는 winodw 객체를 사용하여 라우팅을 처리한다.