프로젝트의 디자인 시스템을 구축하다 보면 중첩된 패스에서 동일한 UI로직을 가지고 있는 경우가 있다. 각 페이지 컴포넌트에 동일한 UI 컴포넌트를 여러 번 선언하면, 페이지 전환 시 불필요한 렌더링이 계속 발생할 수 있으며, 이를 해결하기 위해 고민하다 찾은 방법이 Outlet이다. 먼저 Outlet을 설명하기 위해서는 중첩 라우팅이 무엇인지 알아보도록 하자.

중첩라우팅이란?

중첩 라우팅(Nested Routing)이란 라우팅 맵핑을 최상위 컴포넌트 뿐만 아니라 여러 개의 컴포넌트에 걸쳐서 단계별로 정의하는 라우팅 기법이다.

그럼 중첩라우팅은 어떻게 사용되는 걸까?

예를 들어, 브라우저의 주소 창에 https://www.your-site.com/mypage라고 입력되었을 때, 유저 마이 페이지가 표시되고, https://www.your-site.com/mypage/wish고 입력되었을 때, 위시리스트 페이지가 표시되는 라우팅은 다음과 같이 React Router를 이용하여 단순하게 구현할 수 있다.

<BrowserRouter>
    <Routes>
        <Route path="mypage" element={<Mypage />}>
        <Route path="Wish" element={<Wish />} />
        </Route>
    </Routes>
</BrowserRouter>

React Router - Outlet

React Router란?

https://reactrouter.com/en/main

React Router는 React 애플리케이션에서 클라이언트 사이드 라우팅을 관리하기 위한 라우팅 라이브러리이다. React Router를 사용하여 애플리케이션을 여러 페이지로 나누고, 각 페이지 간의 네비게이션을 쉽게 구현할 수 있다.

예시코드는 아래와 같다.

<Router>
  <Route exact path="/" element={<Home />} />
  <Route path="/users" element={<Users />} />
  <Route path="/articles" element={<Articles />} />
</Router>

React Router- Outlet Component

https://reactrouter.com/en/main/components/outlet

Outlet 컴포넌트는 라우트 매칭 결과를 렌더링하는 데 사용된다. Outlet은 부모 라우트의 역할을 하며, 부모 라우트에 일치하는 하위 라우트를 라우트를 찾은 후 해당 컴포넌트를 렌더링하는 방식으로 라우트 구조의 중첩을 지원하고, 레이아웃을 관리하며, UI를 동적으로 업데이트하는 데 유용하게 사용된다.

Outlet 는 어떻게 사용하는걸까?

import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        {/* 부모 라우트 */}
        <Route path="/" element={<ParentRoute />}>
          {/* 하위 라우트 */}
          <Route path="child1" element={<ChildRoute1 />} />
          <Route path="child2" element={<ChildRoute2 />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};

export default App;

// 부모 라우트 컴포넌트
const ParentRoute = () => {
  return (
    <div>
      <h1>Parent Route</h1>
      {/* Outlet을 통해 하위 라우트를 렌더링 */}
      <Outlet />
    </div>
  );
};

// 하위 라우트 컴포넌트
const ChildRoute1 = () => {
  return (
    <div>
      <h2>Child Route 1</h2>
      <p>This is the first child route.</p>
    </div>
  );
};

const ChildRoute2 = () => {
  return (
    <div>
      <h2>Child Route 2</h2>
      <p>This is the second child route.</p>
    </div>
  );
};