본문 바로가기
React

React에서 Error Boundaries를 활용한 예외 처리

by 굿센스굿 2024. 12. 17.
반응형

 

1. React에서의 예외 처리란?

React 애플리케이션에서 예외(Exception)는 일반적으로 렌더링 중, 이벤트 처리 중, 또는 컴포넌트의 생명주기 메서드에서 발생할 수 있습니다. 이러한 예외를 적절히 처리하지 않으면 애플리케이션이 중단되거나 예기치 않은 오류가 사용자에게 노출될 수 있습니다.

**Error Boundaries(오류 경계)**는 React 16에서 도입된 기능으로, 애플리케이션에서 예외가 발생해도 애플리케이션 전체가 중단되지 않도록 특정 컴포넌트의 오류를 감지하고 처리할 수 있는 방법을 제공합니다.


2. Error Boundaries의 주요 특징

  1. 클래스 컴포넌트에서만 구현 가능
    Error Boundaries는 현재 클래스 컴포넌트에서만 구현할 수 있습니다. 함수형 컴포넌트에서는 React의 useErrorBoundary 같은 외부 라이브러리나 커스텀 훅을 활용해야 합니다.
  2. 잡을 수 있는 에러
    Error Boundaries는 다음과 같은 상황에서 발생하는 에러를 감지합니다:
    • 렌더링 중 발생한 에러
    • 생명주기 메서드(componentDidMount, componentDidUpdate)에서 발생한 에러
    • 자식 컴포넌트의 에러
    하지만, 다음 상황에서는 감지할 수 없습니다:
    • 이벤트 핸들러에서 발생한 에러
    • 비동기 코드(예: setTimeout 또는 async 함수)에서 발생한 에러
    • 서버사이드 렌더링 중 발생한 에러
  3. React 메서드
    Error Boundaries는 주로 두 가지 생명주기 메서드를 활용합니다:
    • static getDerivedStateFromError(error): 발생한 에러를 상태에 반영
    • componentDidCatch(error, info): 발생한 에러를 로깅하거나 추가 작업 수행

3. Error Boundaries 구현하기

Error Boundaries를 활용한 기본 구현 방법을 단계별로 살펴보겠습니다.

3.1 기본 구조 구현

import React, { Component } from "react";

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

    static getDerivedStateFromError(error) {
        // 에러 발생 시 상태 업데이트
        return { hasError: true };
    }

    componentDidCatch(error, errorInfo) {
        // 에러 정보를 로깅하거나 외부 서비스에 보고
        console.error("Error caught by ErrorBoundary:", error, errorInfo);
    }

    render() {
        if (this.state.hasError) {
            // 에러 발생 시 표시할 UI
            return <h1>문제가 발생했습니다. 잠시 후 다시 시도해주세요.</h1>;
        }

        return this.props.children;
    }
}

export default ErrorBoundary;

3.2 Error Boundary 사용하기

ErrorBoundary를 애플리케이션에서 감싸고 싶은 컴포넌트를 래핑합니다.

import React from "react";
import ErrorBoundary from "./ErrorBoundary";
import ProblematicComponent from "./ProblematicComponent";

function App() {
    return (
        <ErrorBoundary>
            <h1>React Error Boundary 예제</h1>
            <ProblematicComponent />
        </ErrorBoundary>
    );
}

export default App;

3.3 에러 발생을 시뮬레이션하는 컴포넌트

import React from "react";

class ProblematicComponent extends React.Component {
    render() {
        // 강제로 에러를 발생
        throw new Error("예상치 못한 에러 발생!");
        return <div>이 문구는 렌더링되지 않습니다.</div>;
    }
}

export default ProblematicComponent;

위 예제를 실행하면 ProblematicComponent에서 에러가 발생해도 애플리케이션 전체가 중단되지 않고, ErrorBoundary가 이를 감지해 대체 UI를 렌더링합니다.


4. Error Boundaries 활용 사례

Error Boundaries는 실제 애플리케이션에서 다양한 상황에 활용될 수 있습니다.

4.1 모듈별로 구분된 Error Boundary

Error Boundary를 애플리케이션 전체가 아닌 특정 모듈이나 기능에만 적용할 수 있습니다.

function App() {
    return (
        <div>
            <ErrorBoundary>
                <FeatureA />
            </ErrorBoundary>
            <ErrorBoundary>
                <FeatureB />
            </ErrorBoundary>
        </div>
    );
}

4.2 로깅 및 사용자 통보

ErrorBoundary에서 발생한 에러를 외부 서비스에 보고하거나 사용자에게 알릴 수 있습니다. 예를 들어, Sentry 같은 오류 추적 서비스를 통합할 수 있습니다.

import * as Sentry from "@sentry/react";

class ErrorBoundary extends React.Component {
    componentDidCatch(error, errorInfo) {
        Sentry.captureException(error, { extra: errorInfo });
        console.error("Error caught by ErrorBoundary:", error, errorInfo);
    }
}

4.3 사용자 친화적인 UI 제공

ErrorBoundary는 발생한 에러의 심각성에 따라 사용자에게 다른 메시지를 제공할 수 있습니다.

render() {
    if (this.state.hasError) {
        return (
            <div>
                <h1>앗! 문제가 발생했어요 😢</h1>
                <p>불편을 드려 죄송합니다. 새로고침하거나 고객센터에 문의해주세요.</p>
                <button onClick={() => window.location.reload()}>새로고침</button>
            </div>
        );
    }

    return this.props.children;
}

5. 함수형 컴포넌트와 Error Boundaries

React 함수형 컴포넌트 자체는 Error Boundaries를 지원하지 않지만, React 18부터는 use 함수와 Error Boundary를 결합하거나 외부 라이브러리를 통해 대체 구현할 수 있습니다.

5.1 외부 라이브러리 활용

React-error-boundary와 같은 라이브러리를 사용하면 함수형 컴포넌트에서도 간단히 오류 처리를 구현할 수 있습니다.

import { ErrorBoundary } from "react-error-boundary";

function FallbackComponent({ error, resetErrorBoundary }) {
    return (
        <div>
            <p>에러가 발생했습니다: {error.message}</p>
            <button onClick={resetErrorBoundary}>다시 시도</button>
        </div>
    );
}

function App() {
    return (
        <ErrorBoundary FallbackComponent={FallbackComponent}>
            <ProblematicComponent />
        </ErrorBoundary>
    );
}

6. Error Boundaries 사용 시 주의점

  1. Eject된 에러 확인
    에러가 발생한 원인을 정확히 이해하기 위해, ErrorBoundary에서 잡은 에러를 디버깅하거나 외부 서비스로 로깅해야 합니다.
  2. 렌더링 이외의 에러는 처리하지 못함
    이벤트 핸들러나 비동기 코드에서 발생하는 예외는 Error Boundaries에서 처리할 수 없습니다. 이를 위해 try-catch 블록 또는 전역 예외 처리기를 추가해야 합니다.
  3. window.addEventListener("error", (event) => { console.error("Unhandled error:", event.error); }); window.addEventListener("unhandledrejection", (event) => { console.error("Unhandled promise rejection:", event.reason); });

7. 마무리

Error Boundaries는 React 애플리케이션의 안정성을 높이는 강력한 도구입니다. 이를 통해 예상치 못한 에러로 인해 애플리케이션 전체가 중단되는 것을 방지할 수 있습니다. 프로젝트에서 Error Boundaries를 적절히 활용하여 더 나은 사용자 경험과 신뢰성을 제공하는 React 애플리케이션을 만들어 보세요!

반응형