Next.js(ver.13)/Routing

Error Handling

ecoEarth 2023. 8. 2. 04:04

Error Handling

error.js는 pgae.js와 같은 Nex.js의 파일컨벤션이다. 

  • Error컴포넌트는 반드시 'use client'로 Client Components화 시켜야 한다.
  • 특정 segment에 특정 에러바운더리를 설정할 수 있다. -> segment별로 page.js가 있는 것처럼
  • 전체 페이지를 다시 로드하지 않고 오류에서 복구를 시도하는 기능을 사용할 수 있다. -> reset() <- 별거 없다. 에러바운더리안에 래핑된 컴포넌트가 re-render된다.
  • 에러바운더리에 설정한 fallback이 활성화되면 오류 경계 외의 레이아웃요소는 해당 state와 interactive UI를 유지하며 오류가 발생한 컴포넌트는 오류를 복구하는 기능을 표시할 수 있다. -> loading.js뿐만 아니라 error.js도 컴포넌트별로 다뤄지네
"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()은 별거없다. 그냥 에러바운더리 내의 컴포넌트만 새로고침하듯, re-rendering시켜주는게 전부다.
          () => reset()
        }
      >
        Try again
      </button>
    </div>
  );
}

global-error.js

  • app/error.js 경계는 루트 app/layout.js 또는 app/template.js 컴포넌트에서 발생하는 오류를 포착하지 못한다.
  • 이러한 루트 컴포넌트에서 발생하는 오류를 구체적으로 처리하려면 루트 앱 디렉터리에 있는 app/global-error.js라는 error.js의 변형을 사용해야한다.
  • 루트 error.js와 달리 global-error.js 에러 바운더리는 전체 애플리케이션을 감싸며, 해당 폴백 컴포넌트가 활성화되면 루트 레이아웃을 대체한다. 따라서 global-error.js는 자체 <html> 및 <body> 태그를 정의해야 한다.
  • global-error.js 에러 바운더리는 다른 error.js 경계가 대부분의 오류를 포착하므로 자주 트리거되지 않을 가능성이 높다.
    ->global-error.js가 멍청해서 에러를 못잡아낸다는 소리가 아니고, 가장 가까운 에러바운더리에서 에러를 핸들링할거니까, 최상단에 위치한 global-error.js는 자주 작동하지 않을거라는 의미다. 만약 global-error.js만 설정하고, 다른 segment에 error바운더리를 설정하지 않았으면 에러가 발생했을때 무조건 global-error가 작동한다. <- ("Errors bubble up to the nearest parent error boundary." -> 부모가 없으면 에러바운더리의 조부모의 조부모까지 달려가서라도 에러를 핸들링하므로)
  • 오류메시지
    • 서버컴포넌트에서 오류가 발생하면, 오류객체에는 민감한 세부정보가 클라이언트에 유출되지 않도록 일반 메시지와 오류를 조금 간략하게 적은 내용만 들어있다.
    • 클라이언트컴포넌트에서 발생하는 오류 객체는 직렬화되며 디버깅을 쉽게 할 수 있도록 원래 오류의 메시지를 포함하고 있다.
'use client'
 
export default function GlobalError({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
  	// global-error에는 반드시 <html>태그와 <body>태그 들어가야함!!
    <html>
      <body>
        <h2>Something went wrong!</h2>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  )
}