error.js
파일 규칙을 사용하면 중첩된 경로에서 런타임 오류를 우아하게 처리할 수 있다.
error.js
파일을 경로 세그먼트 내부에 추가하고 React 컴포넌트를 내보내어 오류 UI를 생성한다.
// app/dashboard/error.tsx
'use client'; // Error components must be Client Components
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error;
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.js
는 중첩된 자식 세그먼트 또는 page.js 컴포넌트를 감싸는 React Error Boundary를 자동으로 생성한다.
error.js
파일에서 내보낸 React 컴포넌트는 대체 컴포넌트로 사용된다.
에러가 에러 바운더리 내에서 발생하면, 에러는 제한되고 대체 컴포넌트가 렌더링된다.
대체 에러 컴포넌트가 활성화된 경우, 에러 바운더리 위의 레이아웃은 상태를 유지하며 상호 작용 가능하며, 에러 컴포넌트는 에러로부터 복구하기 위한 기능을 표시할 수 있다.
에러의 원인은 때때로 일시적일 수 있다. 이러한 경우에는 간단히 다시 시도하는 것만으로 문제를 해결할 수 있다.
에러 컴포넌트는 reset()
함수를 사용하여 사용자가 에러로부터 복구를 시도하도록 유도할 수 있다. 실행되면 해당 함수는 에러 바운더리의 내용을 다시 렌더링하려고 시도한다. 성공적으로 수행되면 대체 에러 컴포넌트는 다시 렌더링 결과로 대체된다.
// app/dashboard/error.tsx
'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>
);
}
특정 파일을 통해 생성된 React 컴포넌트는 특정 중첩 계층 구조로 렌더링된다.
예를 들어, layout.js
와 error.js
파일을 포함하는 두 개의 세그먼트를 가진 중첩된 라우트는 다음과 같이 간소화된 컴포넌트 계층 구조로 렌더링된다.
중첩된 컴포넌트 계층 구조는 중첩된 라우트에서 error.js
파일의 동작에 영향을 준다.
에러는 가장 가까운 부모 에러 바운더리로 버블링된다. 이는 error.js
파일이 해당 중첩된 자식 세그먼트에 대한 에러를 처리할 것을 의미한다. 중첩된 폴더의 다른 수준에 error.js
파일을 배치함으로써 더 세부적이거나 덜 세부적인 에러 UI를 구현할 수 있다.
에러 바운더리는 동일한 세그먼트의 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
컴포넌트에서 발생한 에러를 잡지 않는다.
이러한 루트 컴포넌트에서 에러를 특별히 처리하려면 root app 디렉토리에 위치한 app/global-error.js
라는 error.js의 변형을 사용한다.
루트 error.js
와는 달리, global-error.js
에러 바운더리는 전체 애플리케이션을 감싸며, 활성화될 때 루트 레이아웃을 대체하는 대체 컴포넌트로 사용된다. 이에 따라, global-error.js
는 자체 <html>
및 <body>
태그를 정의해야 한다.
global-error.js
는 가장 세부적이지 않은 에러 UI로, 전체 애플리케이션에 대한 "예외 처리"로 간주될 수 있다. 루트 컴포넌트는 일반적으로 덜 동적이므로 이러한 에러 바운더리에서 많은 에러가 발생할 가능성은 낮다.
global-error.js
가 정의되었더라도, 전역으로 공유되는 UI와 브랜딩이 포함된 루트 레이아웃 내에서 렌더링되는 대체 컴포넌트를 정의하는 root error.js를 정의하는 것이 좋다.
// app/global-error.tsx
'use client';
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.js
파일로 전달하여 error prop
으로 사용한다.
next dev
를 실행할 때, 에러는 서버 컴포넌트에서 클라이언트의 error.js
로 직렬화되어 전달된다.
next start
를 프로덕션 환경에서 실행할 때 보안을 보장하기 위해, 에러와 함께 .digest
가 포함된 일반적인 에러 메시지가 error로 전달된다.
.digest
는 에러 메시지의 해시 값을 포함하며, 이 해시는 서버 로그와 대응하는 데 사용될 수 있다.
[출처]
https://nextjs.org/docs/app/building-your-application/routing/error-handling