[ Routing ] Error Handling

차차·2023년 5월 17일
0

Next Docs

목록 보기
9/34
post-thumbnail

error.js 파일 규칙을 사용하면 중첩된 경로에서 런타임 오류를 우아하게 처리할 수 있다.

  • React 에러 바운더리를 사용하여 경로 세그먼트와 해당 중첩된 자식들을 자동으로 감싼다.
  • 파일 시스템 계층 구조를 사용하여 특정 세그먼트에 맞는 오류 UI를 만들어 세분화 수준을 조정한다.
  • 나머지 앱은 정상 작동한 채로 오류를 해당 세그먼트로 격리한다.
  • 전체 페이지를 새로고침하지 않고 오류에서 복구하려는 기능을 추가한다.

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는 어떻게 동작하는가

  • 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.jserror.js 파일을 포함하는 두 개의 세그먼트를 가진 중첩된 라우트는 다음과 같이 간소화된 컴포넌트 계층 구조로 렌더링된다.

중첩된 컴포넌트 계층 구조는 중첩된 라우트에서 error.js 파일의 동작에 영향을 준다.

  • 에러는 가장 가까운 부모 에러 바운더리로 버블링된다. 이는 error.js 파일이 해당 중첩된 자식 세그먼트에 대한 에러를 처리할 것을 의미한다. 중첩된 폴더의 다른 수준에 error.js 파일을 배치함으로써 더 세부적이거나 덜 세부적인 에러 UI를 구현할 수 있다.

  • 에러 바운더리는 동일한 세그먼트의 layout.js 컴포넌트에서 발생한 에러를 처리하지 않는다. 왜냐하면 에러 바운더리는 해당 레이아웃 컴포넌트 내에 중첩되어 있기 때문이다.


레이아웃에서 에러 처리

error.js 바운더리는 동일한 세그먼트의 layout.jstemplate.js 컴포넌트에서 발생한 에러를 잡지 않는다. 이 계층 구조는 에러가 발생할 때 형제 라우트 사이에서 공유되는 중요한 UI(예: 탐색)가 보이고 기능적인 상태를 유지하기 위해 의도적으로 유지된다.

특정 레이아웃이나 템플릿 내에서 에러를 처리하려면 error.js 파일을 레이아웃의 부모 세그먼트에 배치한다.

루트 레이아웃이나 템플릿 내에서 에러를 처리하려면 global-error.js라는 error.js의 변형을 사용한다.

루트 레이아웃에서 에러 처리

루트 app/error.js 바운더리는 루트 app/layout.jsapp/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

profile
나는야 프린이

0개의 댓글