오류 처리(Error Handling)

오류 처리(Error Handling)

애플리케이션에서 오류는 크게 두 부류로 나눠요. 정상 운영 중에도 발생할 수 있는 예상 오류(expected errors) 와, 버그를 뜻하는 예상치 못한 예외(uncaught exceptions) 죠. Next.js는 이 두 종류를 다르게 다루는데, 어떻게 나눠서 처리하는지 정리할게요.

출처: https://nextjs.org/docs/app/getting-started/error-handling

예상 오류 처리하기

예상 오류는 서버 측 폼 검증이나 실패한 요청처럼 정상 운영 중에 발생할 수 있는 오류예요. 이들은 명시적으로 처리하고 클라이언트에 반환해야 해요.

Server Functions에서

useActionState 훅을 사용해서 Server Functions의 예상 오류를 처리할 수 있어요. 이 오류들에는 try/catch 블록과 throw를 피하고, 예상 오류를 반환값으로 모델링해요. 액션을 useActionState 훅에 넘기고, 반환된 state로 오류 메시지를 표시하면 돼요.

Server Components에서

Server Component 안에서 데이터를 가져올 때, 응답을 사용해서 오류 메시지를 조건부로 렌더링하거나 redirect를 사용할 수 있어요.

Not found

라우트 세그먼트에서 notFound 함수를 호출하고, not-found.js 파일을 사용해서 404 UI를 보여줄 수 있어요.

예상치 못한 예외 처리하기

예상치 못한 예외는 앱의 정상 흐름에서 발생하면 안 되는 예측 불가한 오류로, 버그나 문제를 나타내요. 이들은 오류를 throw해서 처리하며, 그러면 에러 바운더리(error boundary) 가 잡아요.

중첩 에러 바운더리

Next.js는 예상치 못한 예외를 처리할 때 에러 바운더리를 사용해요. 에러 바운더리는 자식 컴포넌트의 오류를 잡아서, 크래시한 컴포넌트 트리 대신 fallback UI를 보여줘요.

라우트 세그먼트 안에 error.js 파일을 추가하고 React 컴포넌트를 export하면 에러 바운더리를 만들 수 있어요. 오류는 가장 가까운 부모 에러 바운더리로 전파돼요. error.tsx 파일을 라우트 계층의 여러 레벨에 배치하면 세분화된 오류 처리가 가능해요.

컴포넌트 레벨 오류 복구를 위해 catchError 함수로 컴포넌트 트리의 어느 부분이든 감쌀 수 있는 에러 바운더리를 만들 수도 있어요.

에러 바운더리는 이벤트 핸들러 안의 오류는 잡지 못해요. 렌더링 중 오류를 잡아서 앱 전체가 크래시하는 대신 fallback UI를 보여주도록 설계됐어요. 이벤트 핸들러나 비동기 코드의 오류는 렌더링 후에 실행되므로 에러 바운더리가 처리하지 못해요. 이런 경우에는 오류를 수동으로 잡아 useStateuseReducer에 저장하고 UI를 갱신해서 사용자에게 알려야 해요. useTransitionstartTransition 안에서 처리되지 않은 오류는 가장 가까운 에러 바운더리로 전파된다는 점도 참고하세요.

전역 오류

드물지만 루트 레이아웃에서의 오류를 global-error.js 파일로 처리할 수 있어요. 이 파일은 루트 app 디렉토리에 있으며, 국제화(internationalization)를 쓸 때도 동작해요. 전역 오류 UI는 활성화될 때 루트 레이아웃·템플릿을 대체하므로 자체 <html><body> 태그를 정의해야 해요.

더 알아보기