에러 핸들링

정호성·2025년 3월 11일

Next.js

목록 보기
14/18

Next.js에서는 서버 및 클라이언트에서 발생하는 에러를 효과적으로 처리할 수 있도록 다양한 에러 핸들링 방식을 제공한다.


1. 전역 에러 핸들링 (error.tsx)

Next.js의 App Router를 사용할 경우, 특정 경로에서 발생하는 에러를 전역적으로 처리하려면 error.tsx 파일을 추가하면 된다.

적용 방법

app/some-route/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>⚠️ 에러가 발생했습니다!</h2>
      <p>{error.message}</p>
      <button onClick={() => reset()}>다시 시도</button>
    </div>
  );
}
  • error.tsx는 클라이언트 컴포넌트여야 하므로 "use client"를 추가해야 한다.
  • error 객체를 통해 에러 메시지를 표시할 수 있다.
  • reset 함수를 호출하면, 현재 경로를 초기화하여 다시 시도할 수 있다.

error.tsxreset 함수는 클라이언트 컴포넌트를 다시 렌더링하지만, 서버 컴포넌트는 다시 실행되지 않으므로 클라이언트에서 발생한 오류만 복구할 수 있다.

모든 경우의 에러를 복구하려면 router.refresh()를 사용해 서버 컴포넌트까지 다시 불러와야 하며, React 18부터 제공되는 startTransition() 내부에서 router.refresh()reset()을 함께 호출하면 UI의 끊김 없이 동기적으로 전체 렌더링을 갱신할 수 있다.

<button
    onClick={() => {
      startTransition(() => {
        // 함수 하나를 인수로 받아서, 해당 함수 내부의 코드를 동기적으로 실행
        router.refresh(); // 현재 페이지에 필요한 서버 컴포넌트들을 다시 불러옴
        reset(); // 에러 상태를 초기화, 컴포넌트들을 다시 렌더링
      });
    }}
>
    다시 시도
</button>

2. 개별 컴포넌트에서 try-catch로 에러 핸들링

서버 컴포넌트나 클라이언트 컴포넌트에서 직접 try-catch 문을 사용하여 에러를 처리할 수도 있다.

async function fetchData() {
  try {
    const res = await fetch("https://api.example.com/data");
    
    if (!res.ok) {
      throw new Error("데이터 불러오기에 실패했습니다.")
    };
    
    return await res.json();
  } catch (error) {
    console.error("데이터 로딩 중 에러 발생:", error);
    
    return null; // 에러 발생 시 기본값 반환
  }
}

export default async function Page() {
  const data = await fetchData();
  
  if (!data) return <p>⚠️ 데이터를 불러오지 못했습니다.</p>;

  return <div>✅ 데이터: {JSON.stringify(data)}</div>;
}
  • 서버에서 데이터를 가져오는 과정에서 try-catch를 사용하여 예외를 처리
  • 에러 발생 시 null 반환 → 페이지에서 에러 메시지를 출력
profile
👨🏻‍💻 Front-End Developer

0개의 댓글