[멋쟁이사자처럼 부트캠프 프론트엔드 14기/REACT] Error Boundary

minji·2025년 9월 11일
post-thumbnail

"내가 오류를 알려줄게!"


오류경계 (Error Boundary)의 필요성

리액트는 렌더링 중 에러가 발생하면, 에러를 발생시킨 UI를 화면에서 없애버린다. (극단적이네..)
사용자 입장에서는 에러가 발생했다고 알려주는게 아니라 화면에서 해당 UI가 갑자기 사려져 버린것이니
무척 당황스러울 것이다.

에러를 발생시킨 UI가 사라지기보다는 그 위치에 어떤 에러가 발생했는지 에러메세지와같은 관련 정보를 보여주는 것이 더 나은 방향이다.
이렇게 등장한 것이 바로 오류경계 (Error Boundary) 이다.

오류경계 (Error Boundary)란?

| 오류 발생시, 발생한 부분에 오류 메세지와 같은 fallback UI를 제공하는 컴포넌트

자바스크립트에서는 에러 핸들링을 try...catch 를 활용하여 진행하였다.
리액트에서는 try...catch 문을 사용할 수 없기때문에 그 기능을 에러 바운더리가 하는 것이다.

그렇다면 ErrorBoundary 컴포넌트는 어떻게 생겼고 어떻게 사용하면 될까?

⚠️ 에러 바운더리는 클래스 컴포넌트로만 만들 수가 있고, 함수형에서는 만들 수가 없다.
그럼 함수형 컴포넌트에서는 에러가 발생해서 UI가 사라져도 속수무책인걸까? 그렇진않다!

클래스/함수형 컴포넌트로 나눠서 살펴보기전에 공통적으로 적용되는 내용이 있다.

에러 바운더리 사용형태

1️⃣ 기본형태

// App 파일기준
<StrictMode>
	<ErrorBoundary>
		<App />
	</ErrorBoundary>
</StrictMode>

위와 같은 형태로 적용시키면 App 컴포넌트 내에서 발생하는 오류는 에러 바운더리가 잡아낼 수 있다.

2️⃣ 중첩형태

다음과같이 ErrorBoundary 컴포넌트를 여러 개 중첩해서도 사용할 수 있다.
중첩하여 사용할 경우에는 ErrorBoundary 컴포넌트를 적용한 부분만 오류 발생시 대체UI로 렌더링되고, 나머지 컴포넌트 영역은 영향을 받지않도 정상작동할 수 있기때문에 필요한 경우 중첩하여 사용하기도 한다.

  <Header />
  <Main>
    <ErrorBoundary FallbackComponent={SectionError}>
      <Section />
    </ErrorBoundary>
    <ErrorBoundary FallbackComponent={WidgetError}>
      <Widget />
    </ErrorBoundary>
  </Main>
  <Footer />

에러 바운더리의 특징

  • 자식 컴포넌트에서 발생한 오류를 감지한다.
  • 오류 발생 시, 지정된 대체UI (fallback)를 렌더링한다.
  • 앱 전체가 아닌 지정한 일부분만 대체UI 로 처리된다. → 필요한 컴포넌트만 에러 바운더리로 감싸줄 수 있다.
  • 에러 바운더리는 렌더링 중 발생한 오류만 잡을 수 있다. 다음의 내용들은 에러 바운더리로 오류를 잡아낼 수 없다.

⚠️ 에러 바운더리로 잡을 수 없는 오류

  • fetch, setTimeout 등과 같은 비동기 코드try...catch 문으로 해결해야한다.
  • 이벤트 핸들러 에서 발생한 오류 → try...catch 문으로 해결해야한다.
  • 서버 사이드 렌더링
  • 자식 컴포넌트가 아닌 에러 경계에서 발생하는 오류

에러 바운더리클래스 컴포넌트와 함수형 컴포넌트의 경우로 나눠서 살펴보자.

클래스 컴포넌트

클래스 컴포넌트에서 에러 바운더리를 만드는 형태는 다음과 같다.

// 클래스 컴포넌트 생성을 위한 Component import
import { Component } from 'react'

export default class ErrorBoundary extends Component {
  state = {
	  hasError: false,
		error: null, 
		info: null
  }

	// 오류에 대한 응답으로 오류 발생 시 state를 업데이트하여 사용자에게 보여줄 메시지부분
  static getDerivedStateFromError(error) {
    return { hasError: true, error }
  }

  // 오류 정보 기록 로직
  componentDidCatch(error, info) {
    this.setState({ info })
  }

  render() {
    const { fallback: DisplayError, children } = this.props
    const { hasError, error, info } = this.state

    // 오류가 있으면 fallback UI 렌더링
    if (hasError) {
      return <DisplayError error={error} errorInfo={info} />
    }

    // 오류가 없으면 정상적으로 자식 컴포넌트 렌더링
    return children
  }
}

static getDerivedStateFromErrorcomponentDidCatch 둘 중 하나 이상을 정의하여 에러 바운더리를 구현하는데, 둘 다 사용하는 것이 일반적이고 기능적으로 권장되는 바이다.

함수형 컴포넌트

함수형으로는 에러 바운더리 컴포넌트를 만들 수 없다면 어떻게 사용할 수 있을까?
이런 상황에서 사용하라고 라이브러리가 있는게 아닐까!

1️⃣ 함수형 컴포넌트에서 에러 바운더리를 사용할 수 있는 첫 번째 방법은 react-error-boundary 라이브러리를 이용하는 것이다.

react-error-boundary 라이브러리를 사용하는 형태는 다음과같다.

import { ErrorBoundary } from 'react-error-boundary'

<StrictMode>
	<ErrorBoundary>
	  <App />
	</ErrorBoundary>
</StrictMode>

2️⃣ 라이브러리를 사용하지 않고도 함수형 컴포넌트에서 에러 바운더리를 구현하길 원한다면, 클래스 컴포넌트로 만든 에러 바운더리 를 만들어 함수형 컴포넌트를 감싸주는 방법이 있다.

두 가지 방법이 있긴하지만 아무래도 라이브러리를 이용하는 것이 편리한 방법이기때문에 꼭 클래스 컴포넌트로 에러 바운더리를 만들어야하는 상황이 아니라면 react-error-boundary 라이브러리를 이용하자! 😉


🔗 참고자료
https://ko.legacy.reactjs.org/docs/error-boundaries.html
https://ko.react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary

profile
FE Developer .mjs

0개의 댓글