프로젝트/COWERKERS

COWERKERS 에러 바운더리

인재재 2024. 12. 13. 00:41

에러바운더리는 리액트16에서 나온 개념으로 js에러를 기록하여 깨진 컴포넌트 대신 폴백 UI를 보여주는 리액트 컴포넌트다.

 

getDerivedStateFromError()와 componentDidCatch()를 정의한 클래스형 컴포넌트를 만들어야 한며,

getDerivedStateFromError()를 사용해서 fallback component를 보여주고, componentDidCatch()를 사용해서 에러 내용을 기록하는 형태로 사용하면 된다.

 

하지만 react-error-boundary 라이브러리로 함수형 컴포넌트방식으로 에러바운더리를 사용할 수 있기 때문에 라이브러리를 이용하여 함수형 컴포넌트 방식으로 구현하였다.

 

 

1. 리액트 쿼리와 에러바운더리 적용 문제

기본적으로 에러바운더리 컴포넌트를 만들어서 적용해주면 되는 줄만 알았는데, 적용되지 않는 문제가 있었다. 

어떤 부분에서 걸리는지 찾아보니 React Query를 사용해 Error Boundary를 구현하기 위해서는 throwOnError 옵션을 사용해 줘야했었다. 

 

useQuery에 throwOnError 옵션을 하나하나 설정하는건 비효율적이기 때문에 QueryClient를 설정할 때 defaultOptions 기본 재시도 횟수를 설정하여 전역적으로 useQuery에 Error Boundary가 적용되도록 하였다.

2. 지나치게 오래 지속되는 로딩상태

에러바운더리를 적용하고 일부러 에러를 유발하여 테스트를 해보려했는데,

에러가 발생할 상황에서만 로딩이 오래 지속되다가 대체 페이지가 표시되는 문제가 있었다.

 

해당 프로젝트는 reactQuery를 사용하고있고, React Query는 기본적으로 에러 발생 시 재시도(retry)를 수행한다.

기본값으로 최대 3번 재시도를 시도한다. 실제로 콘솔에서 확인해보니 3번 재시도를 요청하였다.

 

자동 재시도는 클라이언트 에러시 폴백을 너무 늦게 띄운다는 단점이 있기 때문에 재시도 횟수를 0으로, 재시도를 버튼으로 만들어서 구현하는게 좋을 것 같다는 생각을 하였다.

 

useQuery에 retry 속성을 하나하나 설정하는건 비효율적이기 때문에 QueryClient를 설정할 때 defaultOptions 기본 재시도 횟수를 설정하여 전역적으로 useQuery 재시도 횟수를 적용할 수 있도록 하였다.

 

3. reset 동작 불가 ( 데이터 재갱신 문제 )

에러바운더리로 React Query를 사용하게 되면 button에 onClick 이벤트를 resetBoundary를 사용해 페이지를 렌더링을 다시 시도하도록 했는데,새로고침은 동작하지만 다시 데이터가 갱신되지 않는다.

import { useErrorBoundary } from "react-error-boundary";

function ErrorFallback({ error }) {
  const { resetBoundary } = useErrorBoundary();

  return (
    <div>
      <p>문제가 발생했습니다:</p>
      <pre>{error.message}</pre>
      <button onClick={resetBoundary}>다시 시도</button>
    </div>
  );
}

 

기본적으로 ReactQuery는 캐시 된 데이터를 메모리에 유지하고, 컴포넌트의 마운트 상태와 독립적으로 작동하기 때문이다.

공식문서를 확인해보니 리액트의 에러바운더리를 사용하여 QueryErrorResetBoundary 컴포넌트를 사용하는 방법과 useQueryErrorResetBoundary 훅을 사용하면 해결할 수 있다고 한다.

 

그래서 QueryErrorResetBoundary 컴포넌트가 제공하는 쿼리 에러 상태 초기화 역할을 하는 매개변수로 정상적으로 API를 재요청하도록 하였다 !

 

 

성과 !!

각 페이지마다 isError를 사용하여 에러핸들링을 하거나 에러핸들링을 처리하지 못한 페이지들을 Error Boundaries를 사용해 대체함으로써 전역적으로 에러핸들링을 처리하며 Error 관심사를 분리 !

 

throw new Error()로 페이지에 강제 에러 발생시 폴백 화면
401 에러 발생시 메세지 출력

 

Refector/글로벌에러바운더리 by Injaeeee · Pull Request #163 · team-collabor/coworkers (github.com)

'프로젝트 > COWERKERS' 카테고리의 다른 글

COWERKERS 에러 핸들링  (1) 2024.12.13
버추얼 스크롤 이슈  (0) 2024.11.04