React 16 업그레이드 후 Error Boundary 적용기

배경

회사 프로젝트를 React 15.6에서 16.0으로 업그레이드했다. 가장 눈에 띄는 변화는 Error Boundary였다. 기존에는 컴포넌트에서 발생한 에러가 전체 앱을 크래시시키는 경우가 많았는데, 이제 선언적으로 에러를 처리할 수 있게 되었다.

구현

먼저 최상위 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 className="error-page">
        <h1>문제가 발생했습니다</h1>
        <button onClick={() => window.location.reload()}>새로고침</button>
      </div>;
    }
    return this.props.children;
  }
}

주요 라우트마다 Error Boundary를 배치했다. 특히 써드파티 라이브러리를 사용하는 차트 컴포넌트 주변에 적용하니 효과가 좋았다.

<ErrorBoundary>
  <ChartComponent data={chartData} />
</ErrorBoundary>

주의사항

Error Boundary는 이벤트 핸들러 내부의 에러는 잡지 못한다. 비동기 코드나 이벤트 핸들러는 여전히 try-catch가 필요하다.

handleClick = async () => {
  try {
    await fetchData();
  } catch (error) {
    this.setState({ error });
  }
}

결과

프로덕션에서 전체 앱이 죽는 케이스가 확실히 줄었다. Sentry와 연동해서 에러 로그를 수집하니 사용자가 겪는 문제를 더 빨리 파악할 수 있게 되었다.