error.js
파일 컨벤션은 중첩된 루트들 안에서 우아하게 런타임 에러를 핸들링할 수 있게 도와줍니다.
루트 세그먼트 안에 error.js
파일을 추가하여 에러 UI를 생성하고, 리액트 컴포넌트를 익스포트하세요:
// app/dashboard/error.tsx
'use client'; // 에러 컴포넌트는 반드시 클라이언트 컴포넌트여야 합니다
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error,
reset: () => void;
}) {
useEffect(() => {
// 에러 리포트 서비스에 에러를 기록합니다
console.error(error);
}, [error]);
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={
// 세그먼트를 리렌더링하여 에러로부터 리커버링을 시도합니다
() => reset()
}
>
Try again
</button>
</div>
);
}
error.js
Works (error.js
는 어떻게 동작할까요)error.js
는 자동으로 리액트 에러 바운더리를 생성하고, page.js
컴포넌트 또는 중첩된 자식 세그먼트를 감쌉니다.error.js
파일로부터 익스포트된 리액트 컴포넌트는 폴백 컴포넌트로 사용됩니다.에러의 원인은 종종 일시적일 수 있습니다. 이러한 경우에는 간단하게 다시 시도하는 것을 통해 문제를 해결할 수 있습니다.
에러 컴포넌트는 유저가 에러를 회복하기 위한 시도를 할 수 있도록reset()
함수를 사용할 수 있습니다. 이 함수가 실행되면, 함수는 에러 바운더리의 컨텐츠를 리렌더링 하려는 시도를 할 것입니다. 만약 성공한다면, 폴백 에러 컴포넌트는 리렌더링 결과물로 대치될 것입니다.
// 'use client';
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
);
}
특별한 파일들 (special files)를 통해 생성된 리액트 컴포넌트들은 특정한 중첩 위계 안에서 렌더링 됩니다.
예를 들어, 둘 다 각각의 layout.js
와 error.js
를 포함하고 있는, 한 중첩 루트 안의 두 세그먼트 파일들은 아래의 간소화된 컴포넌트 위계에 따라 렌더됩니다:
중첩된 컴포넌트 위계는 중첩된 루트 전반에 걸쳐 error.js
파일의 행동 양식에 아래와 같은 함의들을 갖습니다:
error.js
파일이 그것의 중첩된 모든 자식 세그먼트들의 에러를 핸들링할 것임을 의미합니다. 한 루트의 중첩된 폴더 안의 다양한 레벨에 error.js
파일을 위치함으로써, 더욱 조밀하거나 덜 복잡한 에러 UI를 만들어낼 수 있습니다.error.js
바운더리는 동일한 세그먼트 안의 layout.js
에서 발생한 에러는 핸들링하지 않습니다. 에러 바운더리는 레이아웃 컴포넌트 안에 포함되기 때문입니다.error.js
바운더리는 동일한 세그먼트 안의 layout.js
나 template.js
컴포넌트 안에서 발생한 에러는 캐치하지 않습니다. 이러한 의도적인 위계는 네비게이션과 같이, 형제 루트들 사이에 공유되는 중요한 UI를 볼 수 있는 상태로 유지시켜주며, 에러가 일어나더라도 잘 동작하도록 합니다.
특정한 레이아웃이나 템플릿 안에서 발생한 에러를 핸들링하려면, error.js
파일을 레이아웃의 부모 세그먼트에 위치시키세요.
루트 레이아웃이나 템플릿 안에서 발생한 에러를 핸들링하려면, global-error.js
라는 error.js
의 배리에이션 파일을 이용하세요.
루트 app/error.js
바운더리는 루트 app/layout.js
나 app/template.js
컴포넌트 안에서 발생한 에러는 캐치하지 않습니다.
특별히 이러한 루트 컴포넌트들 안에서 에러를 핸들링하려면, 루트 app
디렉토리 안에 위치한 error.js
의 배리에이션 파일인 app/global-error.js
를 이용하세요.
루트 error.js
와 달리, global-error.js
에러 바운더리는 애플리케이션 전체를 감싸게 됩니다. 그리고 폴백 컴포넌트가 활성화된 경우에는 루트 레이아웃을 대치하게 됩니다. 이 때문에, global-error.js
에는 반드시 그 안에 <html>
태그와 <body>
태그가 있어야만 합니다.
global-error.js
는 애플리케이션 전체를 위한 "캐치-올" 에러 핸들링 UI가 될 수 있으며, 가장 덜 조밀한 에러 UI입니다. 루트 컴포넌트들은 통상적으로 덜 동적이기 때문에, 자주 발생하진 않을 것입니다. 그리고 다른 error.js
바운더리들이 대부분의 에러를 캐치하게 되겠죠.
global-error.js
가 정의되었더라도, 여전히 폴백 컴포넌트가 전역적으로 공유되는 UI나 브랜딩을 포함하고 있는 루트 레이아웃 안에서 렌더링 될 루트 error.js
를 정의하는 것을 추천합니다.
// app/global-error.tsx
export default function GlobalError({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}
데이터를 가져오는 도중이나 서버 컴포넌트 안에서 발생한 에러의 경우, Next.js는 Error
객체를 가장 가까운 error.js
파일에 error
prop으로 전달합니다.
next dev
가 실행되는 동안, error
은 서버 컴포넌트로부터 클라이언트의 error.js
로 전달되고 시리얼라이즈됩니다. 프로덕션 레벨에서 next start
가 실행되고 있을 때는, 보안을 위해 제네릭한 에러 메세지가 에러 메세지의 해시를 포함한.digest
가 error
에 함께 전달될 겁니다. 이 해시는 상응하는 서버 로그로 사용될 수 있습니다.