본문 바로가기

넥스트

[next.js] 7. 에러 핸들링

반응형
해당 내용은 next.js 공식 문서의 영어를 번역하여 정리된 포스트 입니다. 자세한 내용은 공식 사이트를 참고해 주세요.

 

 오류처리

파일 규칙을 사용하면 중첩된 경로error.js 에서 예기치 않은 런타임 오류를 적절하게 처리할 수 있습니다 .

- React Error Boundary 에서 경로(path) 세그먼트와 중첩된 하위 항목을 자동으로 래핑합니다.
- 세분성을 조정하기 위해 파일 시스템 계층 구조를 사용하여 특정 세그먼트에 맞는 오류 UI를 만듭니다.
- 나머지 애플리케이션 기능을 유지하면서 영향을 받은 세그먼트에 대한 오류를 격리합니다.
- 전체 페이지를 다시 로드하지 않고 오류 복구를 시도하는 기능을 추가합니다.

 

 error.js 경로 세그먼트 내부에 파일을 추가하고 React 구성 요소를 내보내 오류 UI를 만듭니다 .

(개인 정리)  next.js 에서는 error.js 파일을 활용하면, 해당 경로의 라우트에서 에러 발생 시 대체 UI를 보여줄 수 있다.

 

'use client' // 에러 컴포넌트는 클라이언트 컴포넌트여야 한다.
 
import { useEffect } from 'react'
 
export default function Error({
  error,
  reset,
}: {  error: Error   // error 매개변수의 타입을 지정
       reset: () => void // reset 함수의 타입을 지정 :: 매개변수와 반환값이 없는 함수를 의미
   })
{
  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는 React 에러 바운더리(경계)를 자동으로 생성하여 중첩된 자식 세그먼트나 page.js 컴포넌트를 감싸는 역할을 합니다. error.js 파일에서 내보내는 React 컴포넌트(<Error/>)는 대체 컴포넌트로 사용됩니다. 에러 바운더리 내에서 오류가 발생하면 오류가 포함되며 대체 컴포넌트가 렌더링됩니다. 대체 에러 컴포넌트가 활성화된 경우, 에러 바운더리 위의 레이아웃은 상태를 유지하며 상호작용할 수 있으며, 에러 컴포넌트는 에러에서 복구하기 위한 기능을 표시할 수 있습니다.

(개인정리) error.js 는 ErrorBoundary 를 자동으로 생성하고, 에러가 발생하는 경우에는 Error 컴포넌트를 내보내어 Page.js 컴포넌트를 대체한다. 이때 경계 바깥에 있는 Layout 컴포넌트는 에러와 상관없이 화면에 렌더링된다.

 

 오류로부터 복구하기

오류의 원인은 때로는 일시적일 수 있습니다. 이러한 경우에는 간단히 다시 시도하면 문제가 해결될 수 있습니다.

에러 컴포넌트는 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 파일을 사용하여 다음과 같은 단순화된 컴포넌트 계층 구조에 렌더링됩니다.

 

https://nextjs.org/docs/app/building-your-application/routing/error-handling#how-errorjs-works

  중첩된 에러 컴포넌트 계층 구조

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

에러는 가장 가까운 상위 에러 바운더리로 버블링됩니다. 이는 error.js 파일이 모든 중첩된 자식 세그먼트의 에러를 처리한다는 것을 의미합니다. 더 구체적이거나 덜 구체적인 에러 UI는 라우트의 중첩 폴더의 다른 수준에 error.js 파일을 배치하여 달성할 수 있습니다.


에러 바운더리는 같은 세그먼트의 layout.js 컴포넌트에서 발생한 오류를 처리하지 않습니다. 이러한 의도적인 계층 구조로 인해 에러가 발생할 때 중요한 UI(예: 탐색)가 오류가 발생한 경우에도 표시되고 기능을 유지합니다.

특정 레이아웃 내에서 오류를 처리하려면 레이아웃 부모 세그먼트에 error.js 파일을 배치하면 됩니다.

루트 레이아웃 내에서 오류를 처리하려면 app/global-error.js라는 error.js의 변형을 사용하세요.

(개인정리) 중첩된 라우트 경로를 가지는 경우에는 error.js는 자식 컴포넌트와 자식 레이아웃 파일에 대한 모든 에러 처리를 담당한다. 하지만, 같은 경로에 위치한 layout.js 컴포넌트에서 발생하는 에러는 처리하지 않는다(이는 루트 경로에서도 통용). 즉, 해당 경로에서 에러가 발생하더라도 layout.js 컴포넌트는 정상적으로 렌더링된다. 만일 해당 layout,js의 오류를 처리하고자 한다면, 상위 라우트에서 error.js 컴포넌트를 정의하면 된다.

 

  루트 레이아웃 내에서 오류 처리

루트 app/error.js 바운더리는 루트 app/layout.js 또는 app/template.js 컴포넌트에서 발생한 오류를 처리하지 않습니다.

특히 이러한 루트 컴포넌트 내에서 오류를 처리하려면 루트 app 디렉토리에 위치한 app/global-error.js라는 error.js의 변형을 사용하세요.

루트 error.js와 달리, global-error.js 에러 바운더리는 전체 애플리케이션을 감싸며 대체 컴포넌트는 활성화될 때 루트 레이아웃을 대체합니다. 이로 인해 global-error.js는 자체 <html> 및 <body> 태그를 정의해야 합니다.

global-error.js는 가장 구체적이지 않은 에러 UI이며 전체 애플리케이션에 대한 "전체 포괄적인" 오류 처리로 간주될 수 있습니다. 보통 루트 컴포넌트는 덜 동적이므로 다른 에러 바운더리가 대부분의 오류를 처리할 것입니다.

global-error.js가 정의되었더라도 일반적으로 루트 레이아웃 내에서 루트 error.js를 정의하여 루트 레이아웃에 포함된 전역으로 공유되는 UI 및 브랜딩을 렌더링하는 대체 컴포넌트를 정의하는 것이 좋습니다.

// 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>
  )
}

 

(개인정리) 앞서 정리했듯이, error.js 컴포넌트는 자신과 같은 경로의 layout.js 컴포넌트의 에러를 처리하지 않는다. app/ 으로 시작하는 루트 경로도 마찬가지 인데, 이럴 때 사용하는 것이 error.js의 변형 버전인 global-error.js 컴포넌트를 생성하는 것이다. 이를 사용하면 전역적으로 에러를 처리하므로 모든 경로에 대한 에러를 처리할 수 있다. 하지만, global-error.js 를 정의하였다 해도, 별도의 루트 경로의 하위 경로에 위치한 모든 컴포넌트에 대한 에러를 처리하는 루트 error.js 컴포넌트를 생성하는 것이 좋다.

 

 서버 오류 처리

Server Component 내에서 오류가 발생한 경우, Next.js는 (생산 환경에서 민감한 오류 정보가 제거된) 에러 객체를 error.js 파일로 오류 prop으로 전달합니다.

 

 민감한 오류 정보 보호

생산 환경에서 클라이언트로 전달되는 Error 객체는 일반 메시지와 다이제스트 속성만 포함합니다.
이는 클라이언트에 오류에 포함된 잠재적으로 민감한 세부 정보를 누출하지 않도록 하는 보안 조치입니다.

메시지 속성은 오류에 대한 일반 메시지를 포함하고, 다이제스트 속성은 오류의 서버 측 로그에서 해당 오류와 일치시키는 데 사용되는 자동 생성된 해시를 포함합니다.

개발 중에는 클라이언트로 전달되는 Error 객체가 직렬화되어 디버깅을 쉽게 하기 위해 원래 오류의 메시지를 포함합니다.

 


[에러 컴포넌트 관련 공식 문서 내용]

https://nextjs.org/docs/app/api-reference/file-conventions/error

 

File Conventions: error.js | Next.js

Using App Router Features available in /app

nextjs.org

 

반응형

'넥스트' 카테고리의 다른 글

[next.js] 9. 경로 가로채기  (0) 2023.08.31
[next.js] 8. 병렬 라우팅  (0) 2023.08.30
[next.js] 6. 로딩 UI 와 스트리밍  (0) 2023.08.27
[next.js] 5. 동적 라우팅  (0) 2023.08.27
[next.js] 4. Route Groups  (0) 2023.08.26