1. 예상 오류 처리 (Error Handling)
// 기본적인 try-catch를 사용한 오류 처리
async function getData() {
try {
const res = await fetch('https://api.example.com/data')
if (!res.ok) {
throw new Error('Failed to fetch data')
}
return res.json()
} catch (error) {
console.error('Error:', error)
return null // 또는 기본값 반환
}
}
2. 서버 작업에서의 오류 처리 (Server Actions Error Handling)
// app/actions.ts
'use server'
async function serverAction(data: FormData) {
try {
// 서버 작업 수행
const result = await database.save(data)
return { success: true, data: result }
} catch (e) {
// 구체적인 오류 타입 처리
if (e instanceof DatabaseError) {
return { success: false, error: '데이터베이스 오류' }
}
return { success: false, error: '알 수 없는 오류' }
}
}
3. 서버 구성 요소의 오류 처리 (Server Component Error Handling)
// app/ServerComponent.tsx
async function ServerComponent() {
const data = await getData()
if (!data) {
// 오류 상태를 명시적으로 처리
return <div>데이터를 불러오는데 실패했습니다</div>
}
return <div>{data.map(item => <Item key={item.id} {...item} />)}</div>
}
4. 오류 경계 사용 (Error Boundaries)
이 부분이 특히 중요한데, Next.js 13 이상에서는 error.tsx 파일을 사용하여 오류 경계를 구현합니다:
// app/error.tsx
'use client' // 클라이언트 컴포넌트여야 함
interface ErrorBoundaryProps {
error: Error
reset: () => void
}
export default function ErrorBoundary({
error,
reset,
}: ErrorBoundaryProps) {
return (
<div className="error-container">
<h2>문제가 발생했습니다!</h2>
<p>{error.message}</p>
<button onClick={reset}>다시 시도</button>
</div>
)
}
5. 중첩된 경로에서 오류 처리 (Nested Routes Error Handling)
app/
├── error.tsx // 전역 오류 처리
├── layout.tsx
├── page.tsx
└── blog/
├── error.tsx // 블로그 섹션 오류 처리
└── page.tsx
6. 전역 오류 처리 (Global Error Handling)
// app/global-error.tsx
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<h1>심각한 오류가 발생했습니다</h1>
<p>{error.message}</p>
<button onClick={reset}>다시 시도</button>
</body>
</html>
)
}
주요 포인트
1. 계층적 오류 처리
- error.tsx는 가장 가까운 상위 경로에서 오류를 포착
- 더 구체적인 오류 처리가 필요한 경우 하위 경로에 error.tsx 배치
2. 오류 복구 전략
// app/posts/error.tsx
'use client'
export default function ErrorBoundary({
error,
reset,
}: {
error: Error
reset: () => void
}) {
useEffect(() => {
// 오류 로깅
console.error(error)
}, [error])
return (
<div>
<h2>포스트를 불러오는데 실패했습니다</h2>
<button
onClick={() => reset()}
className="retry-button"
>
다시 시도
</button>
</div>
)
}
3. 오류 UI 구성
- 사용자 친화적인 메시지 제공
- 복구 옵션 제시 (reset 함수 활용)
- 필요한 경우 대체 콘텐츠 표시
4. 오류 타입별 처리
try {
await someOperation()
} catch (error) {
if (error instanceof NotFoundError) {
// 404 처리
notFound()
}
if (error instanceof AuthError) {
// 인증 오류 처리
redirect('/login')
}
// 기타 오류는 error.tsx에서 처리되도록 전파
throw error
}
오류 핸들링을 통해
- 예측 가능한 오류 상황을 우아하게 처리
- 사용자 경험 개선
- 디버깅 및 유지보수 용이성 향상
- 애플리케이션의 안정성 확보