[React] Error Boundary 사용하기

이창준·2024년 8월 25일

Error Boundary란?

Error Boundary는 React 컴포넌트의 에러를 감지하여 UI 전체가 무너지는 것을 방지하는 역할을 한다다. 구체적으로, Error Boundary는 자식 컴포넌트 트리 내에서 발생한 자바스크립트 에러를 잡아내고, 폴백 UI(fallback UI)를 표시함으로써 애플리케이션이 "깨지는" 상황을 피할 수 있도록 한다.

Error Boundary는 다음의 생명주기 메서드를 통해 구현할 수 있다:

  • static getDerivedStateFromError(error): 발생한 에러를 기반으로 state를 업데이트하여 폴백 UI를 렌더링
  • componentDidCatch(error, info): 에러 정보를 로깅하거나 분석 도구에 전송

Error Boundary의 구현

Error Boundary는 보통 클래스형 컴포넌트로 구현된다. 아래는 기본적인 Error Boundary의 구현 예시이다.

import React, { Component } from 'react';

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

  static getDerivedStateFromError(error) {
    // 다음 렌더링에서 폴백 UI가 보이도록 상태를 업데이트합니다.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 에러 로깅 서비스를 통해 에러를 기록할 수 있습니다.
    console.error("Error caught in ErrorBoundary: ", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // 폴백 UI를 커스터마이징할 수 있습니다.
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

export default ErrorBoundary;

이렇게 정의한 Error Boundary는 애플리케이션의 중요한 부분에 적용할 수 있다. 예를 들어, 주요 레이아웃이나 페이지 레벨에서 Error Boundary를 적용하여 전체 UI가 깨지는 것을 방지하는 것이다 !

function App() {
  return (
    <ErrorBoundary>
      <MyMainComponent />
    </ErrorBoundary>
  );
}

Error Boundary의 한계

Error Boundary는 모든 종류의 에러를 잡아내지 못한다는 한계점이 있다. 다음과 같은 상황에서는 동작하지 않는다고 한다:

•	이벤트 핸들러 내부에서 발생하는 에러
•	비동기 코드(예: setTimeout, requestAnimationFrame)에서 발생하는 에러
•	서버 사이드 렌더링(SSR) 중 발생하는 에러
•	Error Boundary 자신에서 발생하는 에러

이러한 한계를 이해하고, Error Boundary와 함께 다른 에러 처리 메커니즘을 사용해야 한다. 예를 들어, 이벤트 핸들러 내에서 try-catch 블록을 사용하여 에러를 직접 처리하는 것이다.

Error Boundary를 이용한 에러 처리 전략

1. 적절한 폴백 UI 제공

에러가 발생했을 때 사용자에게 적절한 안내를 제공하는 것이 사용자 경험에 큰 역할을 한다. 단순히 “Something went wrong”라는 메시지보다는, 문제가 발생했음을 알리고, 가능한 경우 이를 해결하기 위한 조치를 안내하는 사용자에게도 좋다.

render() {
  if (this.state.hasError) {
    return (
      <div>
        <h1>Oops! An error occurred.</h1>
        <p>Try refreshing the page, or contact support if the problem persists.</p>
      </div>
    );
  }

  return this.props.children;
}

2. 에러 로깅 및 모니터링

componentDidCatch 메서드를 활용하여 에러 발생 시 이를 외부 서비스로 전송해 로깅할 수 있다. 예를 들어, Sentry나 LogRocket 같은 도구를 사용해 에러를 기록하고, 이를 통해 문제의 근본 원인을 분석할 수 있다.

componentDidCatch(error, errorInfo) {
  logErrorToMyService(error, errorInfo); // 에러를 로깅 서비스로 전송
}

3. 컴포넌트별 Error Boundary 사용

모든 컴포넌트에 대해 하나의 Error Boundary를 사용하는 것보다, 컴포넌트별로 Error Boundary를 적용해 보다 세밀하게 에러를 관리할 수 있다. 예를 들어, 특정 컴포넌트에서만 발생할 수 있는 에러는 해당 컴포넌트에 국한된 폴백 UI를 제공하는 것이 깔끔하다.

function Dashboard() {
  return (
    <ErrorBoundary>
      <WidgetA />
    </ErrorBoundary>
    <ErrorBoundary>
      <WidgetB />
    </ErrorBoundary>
  );
}
profile
개발자가 되고싶은 먼지입니다.

0개의 댓글