안녕하세요!
Justee에 오신 걸 환영합니다.
오늘은 'createBrowserRouter 활용하여 더 깔끔하게 라우트를 구성해보자!'에 대해 이야기해 볼게요.
목차
- createBrowserRouter란 무엇인가?
- BrowserRouter와 createBrowserRouter의 차이점
- errorElement로 에러 처리하기
- loader를 활용한 데이터 로딩 및 로딩 상태 관리
- createBrowserRouter의 장점과 활용 사례
- 언제 createBrowserRouter를 사용해야 할까?
- 마무리하며: 개인적인 소견
정보
1. createBrowserRouter란 무엇인가?
createBrowserRouter는 React Router v6.4에서 새롭게 도입된 라우터 설정 방식입니다.
BrowserRouter는 간단한 라우팅만 제공하지만, createBrowserRouter는 데이터 로드와 에러 처리를 등을 함께 지원합니다.
이전에는 ErrorBoundary, Suspense 등을 이용해서 별도 로직(객체화, 공통화)을 작성하여 작업했는데,
이전보다 더 깔끔하고 간단하게(?) 작업할 수 있는 기대할 수 있습니다.
2. BrowserRouter와 createBrowserRouter의 차이점
기능 | BrowserRouter | createBrowserRouter |
라우팅 방식 | 컴포넌트 기반 라우팅 | 객체 기반 선언적 라우팅 |
폼 처리 (action) |
지원하지 않음 | <form /> 외에도 데이터를 서버와 주고받는 작업을 처리 가능(GET 제외) |
에러 처리 (errorElement) |
지원하지 않음 별도 에러 처리 필요(try-catch 또는 ErrorBoundary) |
errorElement로 에러 처리 가능 |
데이터 로드 (loader) |
지원하지 않음 | loader를 사용해 라우트 전환 시 데이터 미리 로드 가능 |
설정 방식 | 간단한 설정 | 데이터 로직을 포함한 설정 |
활용 방법 | 단순 네비게이션과 페이지 전환이 필요한 프로젝트 | 데이터 로드, 폼 제출, 에러 처리가 필요한 프로젝트 |
BrowserRouter는 간단한 라우팅을 처리하는데 적합하지만, createBrowserRouter는 데이터 로딩과 에러 처리가 필요한 곳에 적합합니다. 객체 기반으로 선언적인 라우트 구성이 가능하며, 데이터 로드와 라우팅을 결합하여 라우트를 관리할 수 있습니다. BrowserRouter에서도 객체 기반 설정이 가능하지만, 추가적인 로직이 필요합니다.
3. errorElement로 에러 처리하기
createBrowserRouter는 에러가 발생했을 때 처리할 수 있는 errorElement 기능을 제공합니다.
데이터 로딩 중 에러가 발생할 경우, 미리 정의된 에러 페이지를 표시할 수 있습니다.
const router = createBrowserRouter([
{
path: '/profile/:userId',
element: <UserProfile />,
loader: userLoader,
errorElement: <ErrorPage />, // 에러 발생 시 표시할 컴포넌트
},
]);
errorElement는 각 라우트마다 설정 가능하며, 발생한 에러를 한 곳에서 처리하여 사용자에게 에러 메시지를 표시할 수 있습니다.
4. loader를 활용한 데이터 로딩 및 로딩 상태 관리
4.1 loader를 활용한 데이터 로딩
loader는 라우트 전환 시 데이터를 미리 로드할 수 있는 기능입니다. 이 기능을 사용하면 페이지 전환 중 서버에서 데이터를 가져와서 컴포넌트에 전달할 수 있습니다. 컴포넌트에서는 이 데이터를 useLoaderData 훅을 통해 사용할 수 있습니다.
const userLoader = async ({ params }) => {
const response = await fetch(`/api/user/${params.userId}`);
if (!response.ok) {
throw new Error('User not found');
}
return response.json();
};
const router = createBrowserRouter([
{
path: '/profile/:userId',
element: <UserProfile />,
loader: userLoader, // 데이터를 미리 로드
},
]);
function UserProfile() {
const user = useLoaderData(); // loader에서 로드된 데이터를 가져옴
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
4.2 loader로 로딩 상태 관리하기
데이터가 로드되는 동안 로딩 상태를 관리하기 위해, loader와 컴포넌트에서 로딩 상태를 직접 처리할 수 있습니다. 컴포넌트 내에서 로딩 중에는 로딩 메시지 등을 표시할 수 있습니다.
import { useLoaderData } from "react-router-dom";
import { useState, useEffect } from "react";
const UserProfile = () => {
const data = useLoaderData();
const [loading, setLoading] = useState(true);
useEffect(() => {
if (data) {
setLoading(false);
}
}, [data]);
if (loading) {
return <div>Loading profile...</div>;
}
return (
<div>
<h1>{data.name}'s Profile</h1>
<p>Email: {data.email}</p>
</div>
);
};
5. createBrowserRouter의 장점과 활용 사례
장점
- 데이터 로딩과 라우팅의 통합: loader를 통해 라우트 전환 시 데이터를 미리 로드할 수 있어, 페이지가 로드될 때 필요한 데이터가 즉시 준비됩니다.
- 중앙 집중화된 에러 처리: errorElement를 통해 각 라우트마다 에러 처리 로직을 작성하지 않고, 한 곳에서 에러를 처리할 수 있습니다.
- 페이지 전환과 폼 제출 관리: action을 통해 폼 제출 및 데이터를 중앙에서 관리할 수 있습니다.
활용 사례
- 대규모 애플리케이션에서 페이지마다 데이터를 로드하고 관리하는 경우.
- 사용자 인터페이스에서 에러와 로딩 상태를 분리하여 처리할 필요가 있을 때.
- 서버에서 데이터를 동적으로 로드해야 하거나 데이터 무결성이 중요한 상황.
6. 언제 createBrowserRouter를 사용해야 할까?
createBrowserRouter는 데이터 로드, 에러 처리, 폼 제출 등 라우팅 외의 추가 작업이 필요한 경우 사용하면 좋습니다.
단순한 라우팅이 필요한 경우 BrowserRouter가 적합하지만, 데이터 흐름(객체 기반)을 함께 관리하고자 한다면 createBrowserRouter가 더 효율적입니다.
7. 마무리하며: 개인적인 소견
이전에 작업할 때는 라우터를 객체 기반으로 구조화하고 별도의 로직을 작성하는 방식으로 진행했지만,
createBrowserRouter를 사용하면서 라우터의 역할을 더 명확하게 분리할 수 있었다고 느꼈습니다. 이제 라우터는 라우팅에 집중하고, 다른 작업들은 더 적합한 위치에서 처리할 수 있게 되어 전체적인 코드가 더 깔끔해진 것 같습니다.
특히, react-query나 zustand 같은 라이브러리를 사용하면 상태 관리와 데이터 페칭을 보다 쉽게 처리할 수 있습니다. 하지만 이 라이브러리들이 있다고 해서 역할이 명확히 구분되는 것은 아닙니다. 결국, 각 도구의 목적에 맞게 역할을 설계하고 관리하는 것은 개발자의 몫입니다. 이러한 라이브러리들은 역할 분리를 돕는 기반을 제공하는 것이라고 생각합니다.
createBrowserRouter를 적절하게 사용하면 효율성을 높일 수 있는 기능이라고 생각합니다. 여러분도 프로젝트에서 각 도구의 역할을 분명하게 나누어 사용해 보시면, 더 깔끔한 코드와 효율적인 작업 방식을 경험할 수 있을 거라 믿습니다.
끝까지 읽어주셔서 감사합니다!
이번 글이 도움이 되셨길 바라며, 궁금한 점이나 잘못된 부분이 있다면 언제든 댓글로 남겨주세요.
그럼 다음 글에서 또 뵙겠습니다!