TIL - 20250829

juni·2025년 8월 29일

TIL

목록 보기
109/317

0829 React Router: 페이지 이동과 동적 라우팅


✅ 1. 기본 라우팅 설정 및 페이지 이동

  • React Router는 싱글 페이지 애플리케이션(SPA)에서 사용자가 URL을 통해 여러 페이지를 이동하는 것처럼 느끼게 해주는 라이브러리입니다. 실제로는 페이지를 새로고침하지 않고, URL에 맞는 컴포넌트만 동적으로 렌더링합니다.

➕ 1-1. 첫 번째 라우팅 하기 (createBrowserRouter)

  • 최신 React Router(v6.4+)에서는 createBrowserRouter를 사용하여 라우트 설정을 객체 형태로 정의합니다.

    // main.jsx 또는 App.jsx
    import { createBrowserRouter, RouterProvider } from 'react-router-dom';
    import HomePage from './pages/Home';
    import ProductsPage from './pages/Products';
    
    // 1. 라우트 경로와 렌더링할 컴포넌트를 배열 객체로 정의
    const router = createBrowserRouter([
      { path: '/', element: <HomePage /> },
      { path: '/products', element: <ProductsPage /> },
    ]);
    
    // 2. RouterProvider를 통해 앱에 라우터 제공
    ReactDOM.createRoot(document.getElementById('root')).render(
      <React.StrictMode>
        <RouterProvider router={router} />
      </React.StrictMode>
    );
  • <a> 태그를 사용하면 안 되는 이유: <a> 태그는 전체 페이지를 새로고침하여 SPA의 장점을 없애버립니다.

  • <Link>: 페이지를 새로고침하지 않고, 지정된 경로(to)로 URL만 변경하여 클라이언트 사이드에서 페이지를 전환합니다.

    import { Link } from 'react-router-dom';
    <Link to="/products">Go to Products</Link>
  • <NavLink>: Link의 특별한 버전으로, 현재 URL과 to prop이 일치할 때 특정 스타일이나 클래스를 적용할 수 있습니다. 주로 네비게이션 바에서 현재 활성화된 메뉴를 표시할 때 사용합니다.

    <NavLink
      to="/products"
      className={({ isActive }) => (isActive ? 'active-link' : undefined)}
    >
      Products
    </NavLink>

✅ 2. 레이아웃과 중첩 라우팅

  • 여러 페이지에서 공통적으로 사용되는 UI(헤더, 푸터 등)를 레이아웃 라우트로 만들어 코드 중복을 줄일 수 있습니다.
  1. 레이아웃 컴포넌트 생성: 공통 UI를 포함하고, 자식 라우트가 렌더링될 위치에 <Outlet /> 컴포넌트를 배치합니다.

  2. 라우터 설정: children 속성을 사용하여 라우트를 중첩시킵니다.

    // components/RootLayout.js
    import { Outlet } from 'react-router-dom';
    import MainNavigation from './MainNavigation';
    
    function RootLayout() {
      return (
        <>
          <MainNavigation />
          <main>
            <Outlet /> {/* 자식 라우트 컴포넌트가 여기에 렌더링됨 */}
          </main>
        </>
      );
    }
    
    // 라우터 설정
    const router = createBrowserRouter([
      {
        path: '/',
        element: <RootLayout />, // 부모 레이아웃
        children: [ // 자식 라우트들
          { path: '/', element: <HomePage /> },
          { path: '/products', element: <ProductsPage /> },
        ],
      },
    ]);

✅ 3. 동적 라우팅: URL 파라미터와 쿼리 스트링

➕ 3-1. URL 파라미터로 라우팅하기 (useParams)

  • 상품 상세 페이지처럼, 특정 ID에 따라 동적으로 페이지를 생성해야 할 때 사용합니다.

  • 경로 설정: 경로에 콜론(:)을 사용하여 동적 세그먼트를 정의합니다. (path: '/products/:productId')

  • 값 읽기: useParams Hook을 사용하여 URL의 동적 파라미터 값을 객체로 가져옵니다.

    // pages/ProductDetail.js
    import { useParams } from 'react-router-dom';
    
    function ProductDetailPage() {
      const params = useParams(); // { productId: 'p1' } 와 같은 객체 반환
    
      return <h1>Product Details for {params.productId}</h1>;
    }

➕ 3-2. 쿼리 스트링 읽고 생성하기 (useSearchParams)

  • 정렬, 필터링 등 선택적인 옵션을 URL에 표현할 때 사용합니다. (/products?sort=asc&filter=new)

  • useSearchParams Hook: [searchParams, setSearchParams] 형태의 배열을 반환합니다.

    • searchParams: 쿼리 스트링을 읽는 객체 (searchParams.get('sort')).
    • setSearchParams: 쿼리 스트링을 프로그래매틱하게 변경하는 함수.
    // components/FilterComponent.js
    import { useSearchParams } from 'react--router-dom';
    
    function FilterComponent() {
      const [searchParams, setSearchParams] = useSearchParams();
      const currentSort = searchParams.get('sort') || 'default';
    
      const handleSortChange = (newSortOrder) => {
        // 쿼리 스트링을 업데이트하여 URL 변경
        setSearchParams({ sort: newSortOrder });
      };
    
      return (
        <div>
          <p>Current sort order: {currentSort}</p>
          <button onClick={() => handleSortChange('asc')}>Sort Ascending</button>
          <button onClick={() => handleSortChange('desc')}>Sort Descending</button>
        </div>
      );
    }

✅ 4. 에러 처리

  • 존재하지 않는 경로로 접근하거나 데이터 로딩에 실패했을 때 보여줄 커스텀 에러 페이지를 설정할 수 있습니다.
  1. errorElement 추가: 라우트 설정 객체에 errorElement 속성을 추가합니다.

  2. useRouteError Hook: 에러 페이지 컴포넌트 내에서 이 Hook을 사용하여 발생한 에러 객체에 접근할 수 있습니다.

    // pages/Error.js
    import { useRouteError } from 'react-router-dom';
    
    function ErrorPage() {
      const error = useRouteError(); // 에러 객체 (status, data 등 포함)
      return (
        <>
          <h1>An error occurred!</h1>
          <p>{error.statusText || error.message}</p>
        </>
      );
    }
    
    // 라우터 설정 (최상위 라우트에 설정하면 모든 하위 에러를 처리)
    const router = createBrowserRouter([
      {
        path: '/',
        element: <RootLayout />,
        errorElement: <ErrorPage />, // 에러 발생 시 이 컴포넌트 렌더링
        children: [ /* ... */ ],
      },
    ]);

📌 요약

  • createBrowserRouter<RouterProvider>로 라우팅을 설정하고, <Link>로 페이지를 새로고침 없이 이동합니다.
  • <Outlet />children 속성을 사용하면 공통 레이아웃을 갖는 중첩 라우팅을 쉽게 구현할 수 있습니다.
  • 필수적인 동적 데이터는 URL 파라미터(useParams)로, 선택적인 필터/정렬 값은 쿼리 스트링(useSearchParams)으로 관리합니다.
  • errorElementuseRouteError를 사용하면 사용자 친화적인 에러 페이지를 제공하여 애플리케이션의 안정성을 높일 수 있습니다.

0개의 댓글