본문 바로가기
C.W.K.
Stream
Lesson 09 of 09 · published

오류 경계와 추적 ID 연결하기

~20 min · error.tsx, global-error.tsx, boundaries

Level 0호기심
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

오류는 가장 가까운 경계로 올라가

app/global-error.tsx        # 루트 레이아웃 오류
  app/layout.tsx
    app/dashboard/error.tsx # 대시보드 페이지와 하위 오류
      app/dashboard/page.tsx
        components

페이지나 하위 컴포넌트에서 난 오류는 가장 가까운 error.tsx가 받아. 이 파일은 상태와 재시도 hook을 사용하므로 클라이언트 컴포넌트여야 해. 다만 자기와 같은 구간의 레이아웃에서 난 오류는 잡지 못하므로 그 위 경계가 필요해.

루트 문서가 깨지면 global-error.tsx가 대신해

app/global-error.tsx는 루트 레이아웃 전체를 대체해. 따라서 자기 <html><body>를 직접 렌더링해야 해. 정상 레이아웃의 provider와 스타일이 없을 수 있다는 조건에서도 오류 메시지가 보여야 해.

화면의 오류와 서버 로그를 같은 사건으로 묶어

경계에서 받은 오류를 Sentry, Datadog, 자체 logger에 보내고 error.digest도 함께 기록해. 서버 로그에 나타난 같은 ID와 사용자의 보고를 연결하면 민감한 상세를 화면에 노출하지 않고도 원인을 찾을 수 있어.

오류 경계마다 사용자가 할 수 있는 다음 행동과 운영자가 받을 신호를 정해. 작은 패널 실패는 재시도하며 나머지 화면을 살리고, 인증 만료는 로그인으로 보내고, 루트 실패는 최소 문서로 복구해야 해. 각 경계에서 의도적으로 오류를 던져 digest와 배포 버전이 추적기에 연결되는지 확인해.

오류 경계는 이벤트 처리기와 서버 밖의 모든 실패를 자동으로 잡는 마법망이 아니야. 예상 가능한 검증 실패를 예외로 만들면 추적기 잡음도 커져. 복구 가능한 결과는 상태로, 프로그래머가 예상하지 못한 실패는 예외로 나누면 경계와 로그가 더 의미 있어. 페이지, 하위 컴포넌트, 같은 구간 layout, 루트 layout에서 각각 오류를 던져 어느 경계가 잡는지 표와 비교해. 사용자 재시도와 Sentry 사건에 같은 digest·요청 ID·배포 SHA가 남는지 보고, 검증 오류는 추적기 예외가 되지 않는지도 확인해.

사용자 화면에는 요청 ID만 보여 주고 원인과 stack은 서버 로그에 남겨. 같은 ID로 경계, 라우트, 외부 의존성의 사건을 연결할 수 있어야 해.

Code

구간별 오류 경계·tsx
// app/dashboard/error.tsx
'use client';
import { useEffect } from 'react';

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // 로거로 전송하고 digest를 서버 로그와 맞춰
    console.error({ digest: error.digest, message: error.message });
  }, [error]);
  return (
    <div className="p-6 text-center">
      <h2 className="text-lg font-semibold">Something went wrong</h2>
      <p className="mt-1 text-sm text-gray-500">{error.message}</p>
      <button onClick={() => reset()} className="mt-4 rounded bg-blue-600 px-3 py-1 text-white">
        Try again
      </button>
    </div>
  );
}
전역 오류에서 루트 레이아웃 대체하기·tsx
// app/global-error.tsx
'use client';
export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <html>
      <body>
        <h1>Something went very wrong</h1>
        <p>{error.digest}</p>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  );
}

External links

Exercise

페이지·하위 컴포넌트·구간 레이아웃·루트 레이아웃에서 오류를 던져. 어느 경계가 잡고 같은 digest가 추적기에 도착하는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.