minstudio

스트리밍(Streaming)과 로딩, 에러 상태 관리

App Router에서는 React SuspenseError Boundary가 파일 시스템에 기본 내장되어 있습니다.

loading.tsx를 추가하면 서버 컴포넌트가 데이터를 패치하는 동안 스켈레톤 UI를 스트리밍(Streaming)하여 사용자 경험(UX)을 극대화합니다. error.tsx는 특정 컴포넌트 트리에 에러가 발생했을 때 전체 페이지가 다운되는 것을 막고, 해당 부분만 에러 UI로 대체하며 복구(Recover) 버튼을 제공할 수 있습니다.

⏳ Suspense와 Error Boundary의 자동 스트리밍 구조 layout.tsx (항상 유지되는 UI) error.tsx (에러 발생 시 이 영역만 교체) loading.tsx (데이터 로딩 중 노출되는 스켈레톤 UI) page.tsx (실제 서버 컴포넌트 렌더링 결과)
// ==========================================
// 📂 app/dashboard/error.tsx
// ==========================================
'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    // 외부 에러 트래킹 서비스(Sentry 등)로 로깅할 수 있습니다.
    console.error(error)
  }, [error])

  return (
    <div className="p-4 bg-red-500/10 border border-red-500 rounded-lg flex flex-col items-center">
      <h2 className="text-red-500 font-bold mb-4">데이터를 불러오는 중 문제가 발생했습니다!</h2>
      <button
        onClick={() => reset()} // 컴포넌트 재렌더링 시도 (Recover)
        className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition"
      >
        다시 시도하기
      </button>
    </div>
  )
}

// ==========================================
// 📂 app/dashboard/loading.tsx
// ==========================================
export default function Loading() {
  // 실제 페이지(page.tsx)가 렌더링되기 전 즉시 브라우저로 스트리밍됩니다.
  return (
    <div className="p-4 space-y-4 animate-pulse">
      <div className="h-8 bg-slate-700 rounded w-1/4"></div>
      <div className="h-32 bg-slate-700 rounded w-full"></div>
      <div className="h-32 bg-slate-700 rounded w-full"></div>
    </div>
  )
}
스트리밍(Streaming)과 로딩, 에러 상태 관리 | Minstudio