3. 에러 핸들링
에러는 예상된 에러(expected errors) 와 예기치 않은 에러(uncaught exceptions) 두 가지 범주로 나눌 수 있다.
✅ 1. 예상된 에러(Expected Errors)는 반환 값으로 처리해야 한다.
- 서버 액션(Server Actions)에서 예상된 에러를 처리할 때는 try/catch를 사용하지 않는 것이 좋다.
- 대신,
useActionState
를 사용하여 에러를 관리하고 클라이언트로 반환하는 것이 바람직하다.
✅ 2. 예기치 않은 에러(uncaught exceptions)는 에러 경계(error boundaries)를 사용해야 한다.
- 예기치 않은 에러를 처리하려면
error.tsx
및global-error.tsx
파일을 활용하여 에러 경계(error boundaries) 를 구현해야 한다. - 이를 통해 애플리케이션이 갑자기 중단되지 않도록 하고, 사용자에게 적절한 대체 UI (fallback UI)를 제공할 수 있다.
1. 예상된 에러(Expected Errors) 처리
예상된 에러는 애플리케이션의 정상적인 동작 중에 발생할 수 있는 에러로, 예를 들면 서버 측 폼 검증 오류나 API 요청 실패 등이 포함된다. 이러한 에러는 명시적으로 처리하여 클라이언트에 반환해야 한다.
✅ 서버 액션(Server Actions)에서의 예상된 에러 처리
"use server";
import { redirect } from "next/navigation";
export async function createUser(prevState: any, formData: FormData) {
const res = await fetch("https://...");
const json = await res.json();
if (!res.ok) {
return { message: "Please enter a valid email" }; // 에러 메시지 반환
}
redirect("/dashboard"); // 성공 시 대시보드로 리디렉션
}
- 위의 예제처럼,
useActionState
훅을 사용하여 서버 액션의 상태를 관리하고 에러를 처리한다. - 예상된 에러는 try/catch로 감싸기보다는 반환 값(return value)으로 처리하는 것이 좋다.
"use client";
import { useActionState } from "react";
import { createUser } from "@/app/actions";
const initialState = {
message: "",
};
export function Signup() {
const [state, formAction, pending] = useActionState(createUser, initialState);
return (
<form action={formAction}>
<label htmlFor="email">Email</label>
<input type="text" id="email" name="email" required />
{/* 에러 메시지 출력 */}
<p aria-live="polite">{state?.message}</p><button disabled={pending}>Sign up</button>
</form>
);
}
❗ useActionState 훅의 사용법
const [state, formAction, pending] = useActionState(createUser, initialState);
// useActionState(action, initialState, permalink?)
useActionState
훅을 사용하여createUser
의 상태를 관리한다.- 위의 코드에서는,
state.message
를 활용하여 에러 메시지를 사용자에게 표시할 수 있다.(state.message
는 예시 코드로, 서버 액션에서 반환하는 데이터 구조에 따라 달라질 수 있다.) pending
값이 true일 경우 버튼을 비활성화하여 중복 요청을 방지할 수 있다.
✅ 서버 컴포넌트(Server Components)에서의 예상된 에러 처리
- 서버 컴포넌트 내부에서 데이터를 가져올 때 응답 상태를 기반으로 에러 메시지를 조건부 렌더링하거나 리디렉션할 수 있다.
export default async function Page() {
const res = await fetch(`https://...`);
const data = await res.json();
if (!res.ok) {
return "There was an error."; // 에러 발생 시 메시지 출력
}
return "..."; // 정상적인 데이터 렌더링
}
2. 예기치 않은 예외(Uncaught Exceptions) 처리
예기치 않은 예외는 애플리케이션의 정상적인 흐름에서 발생하지 말아야 하는 오류로, 코드의 버그나 예측하지 못한 오류가 포함된다.
이러한 오류는 에러 경계(Error Boundaries) 를 사용하여 처리해야 한다.
✅ 에러 경계(Error Boundaries) 사용
- Next.js에서는 에러 경계 컴포넌트를 사용하여 예기치 않은 에러를 처리한다.
- 에러 경계는 자식 컴포넌트에서 발생한 에러를 감지하고, 애플리케이션이 완전히 중단되지 않도록 대체 UI (fallback UI)를 제공한다.
- route 세그먼트 내부에
error.tsx
파일을 추가하고, React Component를 export 하여 에러 경계 컴포넌트를 생성한다.
app/dashboard/error.tsx
(특정 경로에서 에러 경계 적용)
"use client"; // 에러 경계는 반드시 클라이언트 컴포넌트여야 함
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error);
}, [error]);
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={
// Attempt to recover by trying to re-render the segment
() => reset()
}
>
Try again
</button>
</div>
);
}
error.tsx
파일은 특정 경로(app/dashboard
)에서 발생하는 에러를 감지하고 처리하는 에러 경계 역할을 한다.reset()
함수를 호출하면 해당 페이지를 다시 렌더링하여 에러를 해결한다.useEffect
를 사용하여 에러를 콘솔 또는 로깅 서비스에 기록할 수 있다.
✅ 중첩된 에러 경계(Nested Routes Error Handling)
Next.js에서는 에러가 발생한 위치에서 가장 가까운 부모 에러 경계로 버블링(전파) 된다.
즉, 중첩된 라우트에 각각 error.tsx
를 배치하면 더 세밀한 에러 처리가 가능하다.
✅ 글로벌 에러(Global Errors) 처리
전역 에러 처리는 일반적으로 필요하지 않지만, 국제화(i18n)를 사용하는 경우 등에서 유용할 수 있다.
Next.js에서는 app/global-error.tsx
파일을 사용하여 애플리케이션 전체에 대한 에러 처리를 수행할 수 있다.
app/global-error.tsx
(전역 에러 경계)
"use client"; // Error boundaries must be Client Components
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
// global-error must include html and body tags
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}
- 글로벌 에러 경계는 애플리케이션 전체에서 발생하는 오류를 감지한다.
- 주의할 점:
global-error.tsx
는 이 컴포넌트는 전체 레이아웃을 대체하기 때문에,<html>
과<body>
태그를 직접 포함해야 한다.
📝 정리
유형처리 방식
유형 | 설명 |
✅ 예상된 에러 | useActionState 또는 응답 상태를 기반으로 처리 |
✅ 예기치 않은 예외 | error.tsx (에러 경계) 사용 |
✅ 중첩된 에러 경계 | error.tsx 를 다양한 경로에 배치하여 처리 |
✅ 전역 에러 | global-error.tsx 를 활용하여 애플리케이션 전체 에러 처리 |
- 예상된 에러는 반환 값으로 모델링해야 하며, try/catch 사용을 지양해야 함
- 예기치 않은 예외는 에러 경계를 활용하여 처리해야 하며,
error.tsx
또는global-error.tsx
를 적절히 배치하는 것이 중요
출처
https://nextjs.org/docs/app/building-your-application/routing/error-handling
Routing: Error Handling | Next.js
Learn how to display expected errors and handle uncaught exceptions.
nextjs.org
'웹 프로그래밍 > Next.js' 카테고리의 다른 글
[Next.js 공식문서 정리] Routing : 06. Route Groups (0) | 2025.03.29 |
---|---|
[Next.js 공식문서 정리] Routing : 05. Redirecting (0) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 04. Loading UI and Streaming (2) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 02. Linking and Navigating (0) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 01. Layouts and Templates (0) | 2025.03.28 |
Learn Next.js 공식문서 공부 내용 정리 (1) | 2024.12.22 |