← 전체 글로 돌아가기

Next.js

Next.js error.tsx를 붙이고도 에러 화면이 안 나온 이유

App Router에 error.tsx를 추가했는데도 기대한 화면이 보이지 않았다. 경계의 범위와 reset 동작을 확인한 설정 노트.

파일 하나를 추가하면 끝인 줄 알았다

상품 상세 화면에 예외가 나면 기본 오류 페이지 대신 안내 문구를 보이고 싶었다. app/products/error.tsx를 만들었는데, 테스트 중에는 여전히 전체 오류 화면이 보였다. 원인은 error boundary가 잡을 수 있는 오류와 위치를 제가 섞어 생각한 데 있었다.

error.tsx는 자기와 같은 세그먼트의 page.tsx 및 그 아래 렌더링 오류를 감싼다. 반면 그 파일 자체나 상위 layout에서 난 오류는 더 바깥 경계가 필요하다.

클라이언트 컴포넌트여야 한다

에러 UI는 reset을 받아 재시도할 수 있으므로 클라이언트 컴포넌트로 만들었다.

'use client';

export default function Error({ reset }: { error: Error; reset: () => void }) {
  return (
    <section>
      <p>화면을 불러오지 못했습니다.</p>
      <button onClick={() => reset()}>다시 시도</button>
    </section>
  );
}

처음에는 error prop을 안 쓰니 지웠지만, 운영 로그에 식별자를 남길 때는 필요한 정보만 보내는 편이 낫다. 원본 오류 메시지나 사용자 입력을 화면에 그대로 출력하면 안 된다.

재현 위치를 일부러 바꿨다

page.tsx에서 한 번, layout.tsx에서 한 번 throw new Error('test')를 넣어 봤다. 전자는 해당 error UI가 잡았고, layout의 오류는 잡지 못했다. 이 테스트를 하지 않았다면 파일명이 틀렸다고만 생각했을 것이다.

reset()도 만능은 아니다. DB 연결 실패처럼 잠깐 뒤 정상화될 오류에는 의미가 있지만, 잘못 배포한 코드라면 같은 오류를 다시 만들 뿐이다. 버튼에는 재시도라는 의미만 부여하고, 복구 방법은 별도로 제공했다.

배포 전 확인 목록

  • error.tsx'use client'가 있는가
  • 오류를 낸 파일이 경계의 범위 안인가
  • 오류 상세나 토큰이 화면에 노출되지 않는가
  • 재시도가 실제로 새 렌더링을 시작하는가

예외 처리는 보기 좋은 화면보다, 사용자가 다음 행동을 알 수 있게 하는 데서 시작한다고 느꼈다.