모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

22강 / 전체 30강

스타일링 방법들

4분 읽기 조회 6

에러 바운더리(Error Boundary)와 Suspense로 로딩·에러 상태를 선언적으로 처리하는 방법, 프로덕션 수준의 에러 처리 패턴을 배웁니다.

💥 리액트에서 에러는 어디서 잡히는가

컴포넌트 렌더링 중 에러가 발생하면 리액트는 기본적으로 전체 컴포넌트 트리를 언마운트합니다. 사용자는 빈 화면만 봅니다. 이것이 프로덕션 앱에서 에러 바운더리(Error Boundary)가 필요한 이유입니다.

에러 바운더리는 자식 트리에서 발생한 렌더링 에러를 잡아서, 크래시 대신 폴백 UI를 보여줍니다. 마치 try-catch를 컴포넌트 트리 수준에서 적용하는 것입니다.

🛡️ Error Boundary 구현

에러 바운더리는 클래스 컴포넌트로만 만들 수 있습니다. 실무에서는 react-error-boundary 라이브러리를 씁니다:

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

// 에러 발생 시 보여줄 폴백 컴포넌트
function ErrorFallback({
  error,
  resetErrorBoundary,
}: {
  error: Error
  resetErrorBoundary: () => void
}) {
  return (
    <div className="p-6 bg-red-50 rounded-2xl border border-red-100 text-center">
      <p className="text-red-600 font-bold mb-2">오류가 발생했습니다</p>
      <p className="text-sm text-red-500 mb-4">{error.message}</p>
      <button
        onClick={resetErrorBoundary}
        className="px-4 py-2 bg-red-600 text-white rounded-lg text-sm"
      >
        다시 시도
      </button>
    </div>
  )
}

// 사용: 특정 섹션을 ErrorBoundary로 감싸기
function Dashboard() {
  return (
    <div className="space-y-4">
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <UserStats />  {/* 이 안에서 에러 발생해도 나머지 섹션은 정상 */}
      </ErrorBoundary>
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <RecentPosts />
      </ErrorBoundary>
    </div>
  )
}

에러 바운더리를 세밀하게 배치할수록 에러 영향 범위가 좁아집니다. 전체 페이지가 깨지지 않습니다.

⏳ Suspense — 로딩 상태 선언적 처리

Suspense는 자식이 아직 준비되지 않았을 때 폴백을 보여줍니다. 코드 분할(lazy loading)과 함께 가장 많이 씁니다:

import { lazy, Suspense } from 'react'

// 동적 임포트 — 해당 페이지로 이동할 때만 코드 로드
const HeavyChart = lazy(() => import('./components/HeavyChart'))
const AdminPage = lazy(() => import('./pages/AdminPage'))

function App() {
  return (
    <Routes>
      <Route
        path="/admin"
        element={
          <Suspense fallback={<div className="flex items-center justify-center h-96"><Spinner /></div>}>
            <AdminPage />
          </Suspense>
        }
      />
    </Routes>
  )
}

처음 방문 시 청크(chunk)를 다운로드하는 동안 Spinner가 표시됩니다. 이후 방문에서는 이미 캐싱된 코드를 사용하므로 즉시 렌더링됩니다.

🔗 ErrorBoundary + Suspense 조합

실무에서는 두 가지를 함께 씁니다:

function PostSection({ postId }: { postId: number }) {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onError={(error, info) => {
        // 에러 모니터링 서비스(Sentry 등)로 전송
        console.error('에러 발생:', error, info)
      }}
    >
      <Suspense fallback={<PostSkeleton />}>
        <PostContent postId={postId} />
      </Suspense>
    </ErrorBoundary>
  )
}

// 스켈레톤 UI — 실제 콘텐츠 형태를 흉내내는 로딩 플레이스홀더
function PostSkeleton() {
  return (
    <div className="animate-pulse space-y-3">
      <div className="h-6 bg-gray-200 rounded w-3/4" />
      <div className="h-4 bg-gray-200 rounded" />
      <div className="h-4 bg-gray-200 rounded w-5/6" />
    </div>
  )
}

⚠️ 에러 바운더리의 한계

에러 바운더리가 잡지 못하는 에러:

  • 이벤트 핸들러 안의 에러 (try-catch로 직접 처리)
  • 비동기 코드 에러 (useEffect 안 fetch 실패 등)
  • 서버 사이드 렌더링 에러
  • 에러 바운더리 자체에서 발생한 에러

✅ 정리

  • 에러 바운더리: 렌더링 에러를 잡아 폴백 UI를 보여줍니다. react-error-boundary 라이브러리 추천.
  • 세밀한 에러 바운더리 배치로 에러가 전체 페이지에 영향을 주지 않게 합니다.
  • lazy + Suspense로 페이지 코드를 분할해 초기 로딩 속도를 개선합니다.
  • 이벤트 핸들러와 비동기 에러는 try-catch로 직접 처리합니다.

관련 주제

  • CSS Modules
  • 인라인 스타일
  • Tailwind CSS
  • 컴포넌트 스타일 관리 비교
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 리액트 입문 — 컴포넌트로 만드는 웹
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나

📚 시리즈 전체 공유

리액트 입문 — 컴포넌트로 만드는 웹

이 강의가 속한 시리즈는 총 30강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...