오류는 가장 가까운 경계로 올라가
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로 경계, 라우트, 외부 의존성의 사건을 연결할 수 있어야 해.