React 16의 Error Boundary로 컴포넌트 에러 처리하기

문제 상황

운영 중인 대시보드 서비스에서 특정 차트 컴포넌트에 잘못된 데이터가 들어올 경우 전체 페이지가 빈 화면으로 렌더링되는 이슈가 있었다. 개발 환경에서는 에러 스택이 보이지만 프로덕션에서는 사용자에게 아무것도 보이지 않았다.

Error Boundary 도입

React 16에서 새로 추가된 componentDidCatch 라이프사이클 메서드를 사용해 Error Boundary를 구현했다.

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    this.setState({ hasError: true });
    // 에러 로깅 서비스에 전송
    logErrorToService(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <div>차트를 불러올 수 없습니다.</div>;
    }
    return this.props.children;
  }
}

대시보드의 각 위젯을 Error Boundary로 감싸서 특정 위젯에서 에러가 발생해도 다른 위젯은 정상적으로 동작하도록 개선했다.

<Dashboard>
  <ErrorBoundary>
    <SalesChart data={salesData} />
  </ErrorBoundary>
  <ErrorBoundary>
    <UserStats data={userData} />
  </ErrorBoundary>
</Dashboard>

결과

이제 일부 컴포넌트에서 에러가 발생해도 전체 페이지가 깨지지 않고, 해당 영역만 fallback UI를 보여준다. Sentry와 연동해서 프로덕션 에러도 빠르게 파악할 수 있게 되었다.

주의할 점은 Error Boundary가 이벤트 핸들러 내부의 에러는 캐치하지 못한다는 것이다. 이런 경우는 여전히 try-catch를 사용해야 한다.