리액트에서 ui 렌더링 중 에러 발생 시, 흰 화면이 노출되며 리액트 애플리케이션이 중지되게 됩니다. 서버 데이터 필드에 잘못 접근한 경우, 네트워크 혹은 프론트 로직에 인한 오류, 그리고 각종 에러 등에 대해서 일일히 핸들링 하기란 불가능에 가깝습니다.
또한 에러는 날 수 있다 하더라도, 조그만 에러가 애플리케이션 전체를 중단시켜서 화면 전환조차 불가한 불상사는 막아야 할 것입니다. 이러한 에러 핸들링에 가장 편리하고, ui 상으로도 이상적인 방안으로 React16의 ErrorBoundary가 있습니다.
에러 경계는 하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하며 깨진 컴포넌트 트리 대신 폴백 UI를 보여주는 React 컴포넌트입니다. 에러 경계는 렌더링 도중 생명주기 메서드 및 그 아래에 있는 전체 트리에서 에러를 잡아냅니다. (by 리액트 공식 싸이트)
정리하자면
<ErrorBoundary>
<Compoents />
</ErrorBoundary>
의 형태로 에러 바운더리 하위에서 발생한 에러를 캐치하고, 에러 발생 시에는 보여줄 화면을 미리 지정해 둘 수 있다는 것입니다.
에러바운더리는 리액트스럽게 선언적이고 미리 에러 페이지를 설정할 수 있는 등 매우 훌륭합니다만, 개인적으로 단 한가지 아쉬운 점이 있습니다.
바로 공식홈페이지의 안내는 클래스형이라는것..! 입니다.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, errorInfo) {
do something...
}
render() {
if (this.state.hasError) {
return <h1>에러 페이지</h1>;
}
return this.props.children;
}
}
클래스형으로 작성된 ErrorBoundary는 사용하시는 리액트 프로젝트가 대부분의 경우처럼 함수형으로 작성되었을 경우 일관성을 해치게 됩니다. 리액트를 함수형으로 처음 접한 분들에게는 더욱 낯설고, 클래스형의 복잡한 생명주기에 대해 이해가 부족하여 개발에 어려움이 있을 수도 있겠습니다.
react-error-boundary는 현재일(23.08월)기준 Weekly Downloads 330만에 달하는 라이브러리 입니다. 공식 홈페이지에서 안내된 클래스형 errorBoundary와 거의 동일한 기능을 사용하면서도, 최근 리액트 개발의 주류인 함수형으로 errorBoundary를 작성할 수 있습니다.
함수형으로 작성된 errorBoundary라는 것 외에도 장점이 있습니다.
react-error-boundary의 기본 props로는 에러 발생 시 보여줄 컴포넌트인 fallback, fallbackRender 등이 있습니다.
사용예)
<ErrorBoundary
fallbackRender={fallbackProps => <ErrorFallback {...fallbackProps} />}
>
{children}
</ErrorBoundary>
const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
return (
<section>
<div>
<p>이용에 불편을 드려 죄송합니다.</p>
<p>
동일한 현상이 계속될 경우 문의 주시기 바랍니다.
</p>
<button onClick={resetErrorBoundary}>
다시 시도하기
</button>
</div>
</section>
)
}
<ErrorBoundary resetKeys={location.pathname}> {cildren} </ErrorBoundary>
대표적인 서버상태관리 라이브러리인 react-query를 사용하는 경우, errorBoundary에서 에러 발생 후 reset 시 쿼리를 재시도하게 할 수 있습니다. 이 때 react-query의 useQueryErrorResetBoundary 훅을 사용하면, react-query의 QueryErrorResetBoundary 하위에 있는 쿼리 오류를 재설정 합니다. (미설정 시 전역으로 재설정)
const ErrorHandler = () => {
const { reset } = useQueryErrorResetBoundary()
return (
<ErrorBoundary onReset={reset}>
{children}
</ErrorBoundary>
)
}
주의) react-query의 설정에 useErrorBoundary: true 속성을 세팅해줘야 오류 발생 시 errorBoundary에서 감지할 수 있다고 함.
new QueryClient({
queries: {
useErrorBoundary: true
}
})