React 16 RC에서 componentDidCatch로 에러 바운더리 구현하기

배경

프로덕션 환경에서 특정 컴포넌트에서 에러가 발생하면 전체 앱이 흰 화면으로 변하는 문제가 있었다. 사용자 입장에서는 최악의 경험이고, 에러 추적도 어려웠다.

React 16 RC 버전에서 Error Boundaries라는 개념이 추가되어 테스트 환경에 적용해봤다.

구현

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 <h1>문제가 발생했습니다. 새로고침해주세요.</h1>;
    }
    return this.props.children;
  }
}

주요 컴포넌트를 감싸서 사용했다.

<ErrorBoundary>
  <UserProfile />
</ErrorBoundary>

주의점

  • 이벤트 핸들러 내부 에러는 캐치하지 못한다
  • 비동기 코드(setTimeout 등)의 에러도 잡지 못한다
  • ErrorBoundary 자체의 에러는 처리할 수 없다

이벤트 핸들러는 여전히 try-catch로 처리해야 했다.

결과

특정 영역에서 에러가 발생해도 앱 전체가 다운되지 않고, Sentry로 에러 정보를 수집할 수 있게 됐다. React 16 정식 릴리즈 전에 미리 준비해둘 수 있어서 좋았다.

Fiber 아키텍처 변경으로 성능 개선도 기대되는데, 정식 버전이 나오면 프로덕션에 적용할 계획이다.