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>
);
Link와 NavLink 사용하기<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>
레이아웃 컴포넌트 생성: 공통 UI를 포함하고, 자식 라우트가 렌더링될 위치에 <Outlet /> 컴포넌트를 배치합니다.
라우터 설정: 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 /> },
],
},
]);
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>;
}
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>
);
}
errorElement 추가: 라우트 설정 객체에 errorElement 속성을 추가합니다.
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 속성을 사용하면 공통 레이아웃을 갖는 중첩 라우팅을 쉽게 구현할 수 있습니다.useParams)로, 선택적인 필터/정렬 값은 쿼리 스트링(useSearchParams)으로 관리합니다.errorElement와 useRouteError를 사용하면 사용자 친화적인 에러 페이지를 제공하여 애플리케이션의 안정성을 높일 수 있습니다.