에러 처리

Nuxt에서 에러를 포착하고 처리하는 방법을 알아보세요.

Nuxt는 풀스택 프레임워크이기 때문에, 다양한 컨텍스트에서 방지할 수 없는 사용자 런타임 에러가 여러 소스에서 발생할 수 있습니다:

  • Vue 렌더링 라이프사이클 중 발생하는 에러 (SSR & CSR)
  • 서버 및 클라이언트 시작 시 에러 (SSR + CSR)
  • Nitro 서버 라이프사이클 중 발생하는 에러 (server/ 디렉토리)
  • JS 청크 다운로드 중 발생하는 에러
SSR서버 사이드 렌더링(Server-Side Rendering), CSR은 **클라이언트 사이드 렌더링(Client-Side Rendering)**을 의미합니다.

Vue 에러

onErrorCaptured를 사용하여 Vue 에러를 후킹할 수 있습니다.

추가로, Nuxt는 vue:error 훅을 제공하며, 이 훅은 에러가 최상위로 전파될 때 호출됩니다.

에러 리포팅 프레임워크를 사용하는 경우, vueApp.config.errorHandler를 통해 전역 핸들러를 제공할 수 있습니다. 이 핸들러는 처리된 에러를 포함한 모든 Vue 에러를 수신합니다.

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // 에러 처리, 예: 서비스에 리포트
  }

  // 이렇게도 가능
  nuxtApp.hook('vue:error', (error, instance, info) => {
    // 에러 처리, 예: 서비스에 리포트
  })
})
vue:error 훅은 onErrorCaptured 라이프사이클 훅을 기반으로 합니다.

시작 시 에러

Nuxt는 Nuxt 애플리케이션 시작 중 에러가 발생하면 app:error 훅을 호출합니다.

이에는 다음이 포함됩니다:

  • Nuxt 플러그인 실행
  • app:createdapp:beforeMount 훅 처리
  • Vue 앱을 HTML로 렌더링(SSR 중)
  • 앱 마운트(클라이언트 사이드) - 이 경우는 onErrorCaptured 또는 vue:error로 처리해야 합니다.
  • app:mounted 훅 처리

Nitro 서버 에러

현재 이 에러들에 대해 서버 사이드 핸들러를 정의할 수는 없지만, 에러 페이지를 렌더링할 수 있습니다. 자세한 내용은 에러 페이지 렌더링 섹션을 참고하세요.

JS 청크 관련 에러

네트워크 연결 실패나 새로운 배포(이전의 해시된 JS 청크 URL이 무효화됨)로 인해 청크 로딩 에러가 발생할 수 있습니다. Nuxt는 라우트 네비게이션 중 청크 로딩에 실패하면 하드 리로드를 수행하여 청크 로딩 에러를 처리하는 내장 지원을 제공합니다.

이 동작은 experimental.emitRouteChunkErrorfalse로 설정하여(이 에러 후킹을 완전히 비활성화) 변경할 수 있으며, 직접 처리하고 싶다면 manual로 설정할 수 있습니다. 청크 로딩 에러를 직접 처리하고 싶다면 자동 구현 예시를 참고하세요.

에러 페이지

Nuxt에서 치명적인 에러(서버에서 처리되지 않은 에러 또는 클라이언트에서 fatal: true로 생성된 에러)가 발생하면, JSON 응답(Accept: application/json 헤더로 요청 시) 또는 전체 화면 에러 페이지가 렌더링됩니다.

서버 라이프사이클 중 다음과 같은 경우 에러가 발생할 수 있습니다:

  • Nuxt 플러그인 처리 중
  • Vue 앱을 HTML로 렌더링 중
  • 서버 API 라우트에서 에러가 발생한 경우

클라이언트 사이드에서는 다음과 같은 경우 에러가 발생할 수 있습니다:

  • Nuxt 플러그인 처리 중
  • 애플리케이션 마운트 전(app:beforeMount 훅)
  • onErrorCaptured 또는 vue:error 훅으로 처리되지 않은 경우 앱 마운트 시
  • 브라우저에서 Vue 앱이 초기화 및 마운트될 때(app:mounted)
모든 Nuxt 라이프사이클 훅을 알아보세요.

기본 에러 페이지를 커스터마이즈하려면, 애플리케이션의 소스 디렉토리(예: app.vue와 같은 위치)에 ~/error.vue를 추가하세요.

error.vue
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError
})

const handleError = () => clearError({ redirect: '/' })
</script>

<template>
  <div>
    <h2>{{ error?.statusCode }}</h2>
    <button @click="handleError">에러 지우기</button>
  </div>
</template>
error.vue와 그 활용법에 대해 더 알아보세요.

커스텀 에러의 경우, 페이지/컴포넌트 setup 함수에서 호출할 수 있는 onErrorCaptured 컴포저블이나 Nuxt 플러그인에서 설정할 수 있는 vue:error 런타임 훅 사용을 강력히 권장합니다.

plugins/error-handler.ts
export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.hook('vue:error', (err) => {
    //
  })
})

에러 페이지를 제거할 준비가 되면, clearError 헬퍼 함수를 호출할 수 있습니다. 이 함수는 리디렉션할 경로(예: '안전한' 페이지로 이동하고 싶을 때)를 옵션으로 받을 수 있습니다.

Nuxt 플러그인에 의존하는 $routeuseRouter와 같은 것을 사용하기 전에 반드시 확인하세요. 플러그인에서 에러가 발생했다면, 에러를 지우기 전까지는 플러그인이 다시 실행되지 않습니다.
에러 페이지 렌더링은 완전히 별도의 페이지 로드이므로, 등록된 미들웨어가 다시 실행됩니다. 미들웨어에서 에러가 처리 중인지 확인하려면 useError를 사용할 수 있습니다.
Node 16에서 에러 페이지 렌더링 시 쿠키를 설정하면, 이전에 설정된 쿠키가 덮어써집니다. Node 16은 2023년 9월에 지원이 종료되었으므로, 더 최신 버전의 Node 사용을 권장합니다.

에러 유틸리티

useError

TS Signature
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

이 함수는 현재 처리 중인 전역 Nuxt 에러를 반환합니다.

useError 컴포저블에 대해 더 알아보세요.

createError

TS Signature
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error

추가 메타데이터가 포함된 에러 객체를 생성합니다. 에러 message로 설정할 문자열이나 에러 속성을 포함하는 객체를 전달할 수 있습니다. 이 함수는 앱의 Vue와 서버 부분 모두에서 사용할 수 있으며, throw를 위해 설계되었습니다.

createError로 생성한 에러를 throw하면:

  • 서버 사이드에서는 전체 화면 에러 페이지가 표시되며, clearError로 지울 수 있습니다.
  • 클라이언트 사이드에서는 비치명적 에러가 throw되어 직접 처리할 수 있습니다. 전체 화면 에러 페이지를 표시하려면 fatal: true를 설정하면 됩니다.
pages/movies/[slug].vue
<script setup lang="ts">
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)

if (!data.value) {
  throw createError({
    statusCode: 404,
    statusMessage: '페이지를 찾을 수 없습니다'
  })
}
</script>
createError 유틸에 대해 더 알아보세요.

showError

TS Signature
function showError (err: string | Error | { statusCode, statusMessage }): Error

이 함수는 클라이언트 사이드 어디서든, 또는(서버 사이드에서는) 미들웨어, 플러그인, setup() 함수 내에서 직접 호출할 수 있습니다. 전체 화면 에러 페이지가 표시되며, clearError로 지울 수 있습니다.

대신 throw createError() 사용을 권장합니다.

showError 유틸에 대해 더 알아보세요.

clearError

TS Signature
function clearError (options?: { redirect?: string }): Promise<void>

이 함수는 현재 처리 중인 Nuxt 에러를 지웁니다. 또한 리디렉션할 경로(예: '안전한' 페이지로 이동하고 싶을 때)를 옵션으로 받을 수 있습니다.

clearError 유틸에 대해 더 알아보세요.

컴포넌트에서 에러 렌더링

Nuxt는 또한 앱 내에서 클라이언트 사이드 에러를 전체 사이트 에러 페이지로 대체하지 않고 처리할 수 있는 <NuxtErrorBoundary> 컴포넌트를 제공합니다.

이 컴포넌트는 기본 슬롯 내에서 발생한 에러를 처리합니다. 클라이언트 사이드에서는 에러가 최상위로 전파되는 것을 막고, 대신 #error 슬롯을 렌더링합니다.

#error 슬롯은 error를 prop으로 받습니다. (error = null로 설정하면 기본 슬롯이 다시 렌더링됩니다. 단, 에러가 완전히 해결된 후에만 해야 하며, 그렇지 않으면 에러 슬롯이 다시 렌더링됩니다.)

다른 라우트로 이동하면 에러가 자동으로 지워집니다.
pages/index.vue
<template>
  <!-- 일부 콘텐츠 -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- 기본 슬롯을 사용해 콘텐츠를 렌더링합니다 -->
    <template #error="{ error, clearError }">
      여기에서 에러를 로컬로 표시할 수 있습니다: {{ error }}
      <button @click="clearError">
        이 버튼을 누르면 에러가 지워집니다.
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
Read and edit a live example in Docs > Examples > Advanced > Error Handling.