stack-analysis
CHAPTER 20 / 90
읽기 약 2분
FUNCTION
에러 바운더리 + 로딩 UI + 스트리밍 SSR
핵심 개념
error.tsx·not-found.tsx·loading.tsx·streaming — 견고한 사용자 경험.
본문
error.tsx (자동 Error Boundary)
// app/posts/error.tsx
'use client';
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Sentry 등에 보고
console.error('Posts error:', error);
}, [error]);
return (
<div className="error-container">
<h2>문제가 발생했습니다</h2>
<p>{error.message}</p>
{error.digest && (
<p style={{ fontSize: 12, color: '#999' }}>참조 ID: {error.digest}</p>
)}
<button onClick={() => reset()}>다시 시도</button>
</div>
);
}
// 글로벌 (root layout 에러)
// app/global-error.tsx
'use client';
export default function GlobalError({ error, reset }: { ... }) {
return (
<html>
<body>
<h1>심각한 오류</h1>
<button onClick={reset}>재시도</button>
</body>
</html>
);
}not-found.tsx
// app/posts/[slug]/page.tsx
import { notFound } from 'next/navigation';
export default async function Page({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
if (!post) notFound(); // → not-found.tsx 렌더
return <article>{post.content}</article>;
}
// app/posts/[slug]/not-found.tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div>
<h2>글을 찾을 수 없습니다</h2>
<Link href="/posts">목록으로</Link>
</div>
);
}loading.tsx + Suspense 조합
// app/dashboard/loading.tsx — 페이지 전체 로딩
export default function Loading() {
return <DashboardSkeleton />;
}
// app/dashboard/page.tsx — 부분 Suspense
import { Suspense } from 'react';
export default function Dashboard() {
return (
<>
<Header /> {/* 빠른 부분 */}
<Suspense fallback={<ChartSkeleton />}>
<SlowChart />
</Suspense>
</>
);
}Streaming SSR — Suspense Boundaries
// 페이지 응답 흐름:
// 1. <html><head>...</head><body>
// 2. <Header />
// 3. <ChartSkeleton /> ← 즉시 표시
// 4. ... (데이터 fetch 중)
// 5. <script>renderChart(data)</script> ← 준비 시 교체
// 6. </body></html>
// 결과:
// - TTFB: 빠름 (즉시 시작)
// - LCP: 빠름 (Header + Skeleton)
// - 차트는 준비되면 자동 교체React Error Boundary 패턴
// 컴포넌트 단위 — react-error-boundary
import { ErrorBoundary } from 'react-error-boundary';
function FallbackComponent({ error, resetErrorBoundary }: any) {
return (
<div role="alert">
<p>오류: {error.message}</p>
<button onClick={resetErrorBoundary}>재시도</button>
</div>
);
}
<ErrorBoundary FallbackComponent={FallbackComponent}>
<RiskyComponent />
</ErrorBoundary>Sentry 통합
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.1,
replaysSessionSampleRate: 0.0,
replaysOnErrorSampleRate: 1.0,
});
// app/error.tsx에서 자동 호출
'use client';
import * as Sentry from '@sentry/nextjs';
import { useEffect } from 'react';
export default function Error({ error }: { error: Error }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return <div>오류 발생</div>;
}다음 모듈
CH.21~26 "CSS·디자인 시스템" — Tailwind 심화.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 에러 처리 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
에러 처리 관련 인기 라이브러리/패턴 5개를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 에러 처리 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 프론트엔드 시장의 에러 처리 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
에러 바운더리 + 로딩 UI + 스트리밍 SSR는 이 3가지만 확실히 잡으세요
1.error.tsx·not-found.tsx·loading.tsx 자동 처리 — Next.js App Router 표준
2.Streaming SSR = TTFB 빠름 + 점진 렌더 + Suspense Boundary로 세분
3.Sentry로 error.tsx 통합 — 프로덕션 에러 추적 표준
공유하기
진행도 20 / 90