
이번 글에서는 사이드 프로젝트를 진행하면서 Error Boundary를 이용한 에러 처리 경험을 정리하여 글로 남겨 보려고 합니다.
보통 에러 처리를 하는 경우 try-catch, error 객체가 있을 때 로직을 분기하는 등의 코드를 작성하곤 했습니다. 하지만 React 16에서 도입된 Error Boundary와 React 18에서 도입된 Suspense를 이용하면 보다 효과적으로 에러 처리를 할 수 있었습니다.
먼저 Suspense부터 알아보도록 하겠습니다.
Suspense를 사용하면 자식이 로딩을 완료할 때까지 폴백을 표시할 수 있습니다.
아래 코드는 리액트 공식문서에 있는 코드입니다
<Suspense fallback={<Loading />}>
<SomeComponent />
</Suspense>
Suspense 컴포넌트의 fallback에 자식이 로딩되는 시간에 표시해줄 컴포넌트를 넘겨줍니다. 보통 이런 경우에는 로딩 시간동안 표시해줄 컴포넌트를 넘겨주면 되겠죠?
저는 아래 코드와 같이 사용했습니다.
<Suspense fallback={<Loader />}>
<TagList tagType={tagType} searchKeyword={searchInput.value} />
</Suspense>
TagList 컴포넌트가 로딩되는 동안 Suspense의 fallback으로 Loader 컴포넌트를 넘겨주었죠. 그리고 비동기 함수를 TagList 컴포넌트에서 호출했습니다.
const TagList = ({ tagType, searchKeyword = '' }: IProps) => {
... code ...
const { data: tagList } = useGetTagQuery(tagType);
... code ...
};
그리고 react-query를 이용하여 데이터 패칭 상태를 반환받도록 구현했습니다.
/** 태그 목록 가져오는 쿼리 */
export const useGetTagQuery = (tagType: string) => {
return useQuery(['tagList', tagType], () => TagApi.get({ tagType }), {
suspense: true,
useErrorBoundary: true,
retry: false,
refetchOnWindowFocus: false,
});
};
// 조회
get = async ({ tagType }: IGet) => {
const { data } = await axiosInstance.get(`/api/tag/view/${tagType}`);
return data;
};
위 두 코드를 이용하여 useGetTagQuery는 data, isLoading, error등을 리턴하게 됩니다.
Error Boundary는 하위 컴포넌트 트리에서 발생한 에러를 잡아서 선언적으로 처리할 수 있는 컴포넌트입니다. 렌더링 중에 throw 된 error를 catch하도록 동작합니다.
Error Boundary는 리액트의 클래스형 컴포넌트로 직접 생명주기별로 동작 코드를 작성하여 구현할 수 있습니다. 직접 구현은 해보았지만 편의성을 위해 라이브러리를 사용하도록 하겠습니다.
기회가 된다면 클래스형 컴포넌트에서 직접 Error Boundary를 구현하여 자세히 다루는 글을 작성해보도록 하겠습니다. 이번 글은 사용기에 가까운 글이니 실사용 코드 위주로 봐주세요!
yarn add react-error-boundary
or
npm i react-error-boundary
라이브러리는 위 명령어를 통해 설치할 수 있습니다.
라이브러리를 사용하면 Error Boundary를 사용하는 방법이 매우 간단합니다.
아래 코드는 Suspense와 Error Boundary를 적용한 코드인데요?
<ErrorBoundary fallbackRender={ErrorFallback} onReset={reset}>
<Suspense fallback={<Loader />}>
<TagList tagType={tagType} searchKeyword={searchInput.value} />
</Suspense>
</ErrorBoundary>
TagList 컴포넌트에서 react-query를 통해 isLoading상태가 반환되면 Suspense에서 감지하여 Loader컴포넌트를 보여주고, 만약 error를 throw하게 되면 ErrorBoundary에서 감지하여 fallbackRender가 화면에 렌더링되게 됩니다.
추가로 onReset입니다.
useQueryErrorResetBoundary 훅을 통해 하위에 있는 모든 쿼리 오류를 재설정할 수 있습니다.
위 코드들은 현재 제가 개발중인 술닥술닥 어드민에서 사용중인 코드이며, 자세한 코드는 아래 주소에서 확인하실 수 있습니다.
술닥술닥 깃허브
긴 글 읽어주셔서 감사합니다 :D