React에서 프로덕션 레디 에러 바운더리: 우아한 실패를 위한 패턴

발행: (2026년 4월 7일 PM 05:52 GMT+9)
5 분 소요
원문: Dev.to

Source: Dev.to

처리되지 않은 렌더링 오류는 전체 React 트리를 충돌시킵니다. 오류 경계는 손상을 차단합니다. 여기서는 프로덕션에서 이를 효과적으로 사용하는 방법을 소개합니다.

문제

// If UserCard throws, the entire page goes blank
function Dashboard() {
  return (
    <>
      {/* if this throws, everything dies */}
    </>
  )
}

기본 오류 경계

오류 경계는 현재 클래스 컴포넌트여야 합니다:

import React, { Component, ReactNode } from 'react'

interface Props {
  children: ReactNode
  fallback?: ReactNode
}

interface State {
  hasError: boolean
  error: Error | null
}

class ErrorBoundary extends Component<Props, State> {
  state: State = { hasError: false, error: null }

  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    console.error('ErrorBoundary caught:', error, info.componentStack)
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback ?? <>Something went wrong</>
    }
    return this.props.children
  }
}

react-error-boundary 사용하기

직접 구현하지 말고 검증된 라이브러리를 사용하세요:

npm install react-error-boundary
import { ErrorBoundary, FallbackProps } from 'react-error-boundary'

function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
  return (
    <>
      <h2>Something went wrong</h2>
      <p>{error.message}</p>
      <button onClick={resetErrorBoundary}>Try again</button>
    </>
  )
}

function Dashboard() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      {/* Your dashboard content */}
    </ErrorBoundary>
  )
}

세분화된 경계

독립적인 섹션을 감싸세요 — 하나에서 발생한 오류가 다른 섹션에 영향을 주어서는 안 됩니다:

function Dashboard() {
  return (
    <>
      <ErrorBoundary FallbackComponent={WidgetError}>
        {/* Widget A */}
      </ErrorBoundary>

      <ErrorBoundary FallbackComponent={WidgetError}>
        {/* Widget B */}
      </ErrorBoundary>

      <ErrorBoundary FallbackComponent={WidgetError}>
        {/* Widget C */}
      </ErrorBoundary>
    </>
  )
}

function WidgetError({ error, resetErrorBoundary }: FallbackProps) {
  return (
    <>
      <p>Failed to load widget</p>
      <button onClick={resetErrorBoundary}>Retry</button>
    </>
  )
}

오류 모니터링 서비스에 로깅하기

import * as Sentry from '@sentry/nextjs'

function onError(error: Error, info: { componentStack: string }) {
  Sentry.captureException(error, {
    extra: { componentStack: info.componentStack },
  })
}

라우트 변경 시 리셋

import { useLocation } from 'react-router-dom'
import { ErrorBoundary } from 'react-error-boundary'

function App() {
  const location = useLocation()

  return (
    <ErrorBoundary
      onReset={() => {
        // Reset logic when the route changes
      }}
      resetKeys={[location.pathname]}
    >
      {/* Your app routes */}
    </ErrorBoundary>
  )
}

Error Boundary가 잡지 못하는 오류

  • 이벤트 핸들러 내부의 오류 (try/catch를 핸들러 안에서 사용)
  • 비동기 코드에서 발생하는 오류 (try/catch와 컴포넌트 상태로 처리)
  • SSR 중 발생하는 오류
  • Boundary 컴포넌트 자체에서 발생하는 오류
// This WON’T be caught by an error boundary:
function Button() {
  const handleClick = async () => {
    try {
      await submitForm() // async error — handle here
    } catch (err) {
      setError(err.message)
    }
  }
  return <button onClick={handleClick}>Submit</button>
}

Next.js의 라우트‑레벨 경계

Next.js App Router에서는 error.tsx를 사용합니다:

// app/dashboard/error.tsx
'use client'

export default function DashboardError({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <>
      <h2>Dashboard failed to load</h2>
      <button onClick={reset}>Try again</button>
    </>
  )
}

이 파일은 전체 /dashboard 라우트 세그먼트에 대한 내장 오류 경계 역할을 합니다.

Production Checklist

  • Next.js의 라우트 수준 error.tsx 파일
  • 독립 위젯 주위의 세분화된 경계
  • 오류 보고 연동 (Sentry / LogRocket)
  • 의미 있는 폴백 UI (단순 흰 화면이 아님)
  • 사용자가 복구할 수 있도록 리셋 버튼
  • 이벤트 핸들러에서 비동기 오류 처리

The AI SaaS Starter Kit 은 Sentry가 통합되고, 라우트 수준 오류 경계가 설정되며, 모든 프로덕션 오류 처리 패턴이 사전 구성되어 제공됩니다. 일회성 $99 — 복제하고 바로 배포하세요.

0 조회
Back to Blog

관련 글

더 보기 »

ECMA2025-최신 진화

ECMAScript 2025 최신 언어 기능 – 이터레이터 헬퍼 .map, .filter, .take, .drop과 같은 새로운 메서드가 이제 이터레이터에서 직접 lazy evaluation으로 동작합니다,…