createError를 불렀는데 404 화면이 안 뜬 이유
문제 발생
없는 글에 접근했을 때 404를 보여주려고 오류를 던졌는데, 서버에서는 전체 화면 오류 페이지가 뜨고 클라이언트 이동에서는 아무 일도 일어나지 않았습니다.
<script setup>
const post = await findPost(route.params.slug);
if (!post) {
createError({ statusCode: 404 }); // ❌ throw 하지 않음
}
</script>error.vue를 만들고 나서는 그 화면에서 빠져나올 수가 없었습니다.
원인 분석
createError는 오류 객체를 만들기만 합니다. 던져야 동작합니다.
그리고 던졌을 때의 동작이 실행 위치에 따라 다릅니다. Nuxt 공식 문서가 나눠서 설명합니다.
- 서버에서 던지면 전체 화면 오류 페이지가 뜨고,
clearError로 지울 수 있습니다. - 클라이언트에서 던지면 치명적이지 않은(non-fatal) 오류가 던져져 우리가 직접 처리하게 됩니다. 전체 화면 오류 페이지가 필요하면
fatal: true를 설정합니다.
error.vue에서 못 빠져나온 이유도 문서에 있습니다 — 이 컴포넌트는 앱 루트에 두는 오류 경계이며(pages/가 아닙니다), 정상 렌더링으로 돌아가려면 clearError()를 호출해야 합니다. 그리고 오류 페이지를 렌더하는 것은 완전히 별개의 페이지 로드라서, 등록된 미들웨어가 다시 실행됩니다.
해결 방안
throw를 붙이고 상태 코드를 명시합니다.
<script setup>
const post = await findPost(route.params.slug);
if (!post) {
throw createError({
statusCode: 404,
statusMessage: "글을 찾을 수 없습니다",
fatal: true,
});
}
</script>error.vue는 앱 루트에 둡니다.pages/안에 넣으면 그냥 페이지가 됩니다.
<!-- error.vue -->
<script setup>
const props = defineProps({ error: Object });
</script>
<template>
<main>
<h1>{{ error.statusCode === 404 ? "없는 페이지입니다" : "오류가 발생했습니다" }}</h1>
<button @click="clearError({ redirect: '/' })">홈으로</button>
</main>
</template>-
clearError에redirect를 줍니다. 오류 상태만 지우면 같은 자리에 남습니다. 안전한 곳으로 함께 보냅니다. -
추가 정보는
data에 담습니다.statusCode,statusText,message,data,cause,stack을 넘길 수 있습니다. 화면에서 분기해야 하는 값은data에 둡니다.
throw createError({ statusCode: 403, data: { reason: "not-owner" } });-
운영에서는 원인이 노출되지 않습니다. 문서가 명시합니다 — 개발 환경에서는 오류의
cause가 보존되어 오류 페이지에 노출되므로 원본 오류를 추적할 수 있지만, 운영에서는cause가 오류 응답이나 오류 페이지 payload에 절대 포함되지 않습니다. 그래서 화면에 원인을 그리는 코드는 로컬에서만 동작하는 것처럼 보입니다. 진단은 서버 로그로 합니다. -
showError보다throw createError()를 씁니다. 문서의 권장 형태입니다.showError도 전체 화면 오류 페이지를 띄우지만, 던지는 쪽이 흐름을 그 자리에서 끊어 의도가 분명합니다. -
오류 페이지에서 데이터를 다시 부르지 않습니다. 별개의 페이지 로드라 미들웨어가 다시 도는데, 그 미들웨어가 또 실패하면 순환합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.