Nuxt.js 에서는 예기치 않은 에러 발생시, layout 폴더 하위에 error.vue 파일을 이용하면 아주 쉽게 에러 페이지를 커스터마이징 할 수 있다.
(이걸 모르고 에러 페이지를 따로 만들어서 라우터를 태우는 뻘짓을 한 사람,,)
먼저 layout 디렉토리에 error.vue 파일을 생성한다.
<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
<script>
export default {
props: ['error'],
layout: 'errorLayout'
}
</script>
layout에 'errorLayout'이라는 커스터마이징한 레이아웃을 설정할 수 있고, props에 'error'를 넣으면 nuxt.js에서 관리하는 error 객체를 사용할 수 있다.
그렇다면 error.vue에서 props로 전달되는 error 객체를 어떻게 다룰 수 있을까?
쉽다. 에러 페이지로 전달하고 싶을 때 nuxt.js에서 제공하는 에러 객체에 에러 코드나 에러 메시지 등을 전달하면 된다.
현재 진행하고 있는 프로젝트에서는 nuxt.js에서 제공하는 미들웨어 기능을 사용해 라우팅 처리를 진행중인데, 이 때 사용자가 존재하지 않거나 접근 권한이 없는 페이지로 진입하려고 했을 때 에러 페이지로 라우터를 변경할 수 있다.
// 사용자 권한에 따라 사용할 수 있는 view가 아닌 경우 route error 처리
if (!view) {
return ctx.error({ statusCode: 404, message: 'Route Error' })
}
위와 같이 미들웨어에서 접근 가능한 ctx에서 error 핸들러를 통해 에러 코드와 에러 메시지를 props로 전달할 수 있다.
이러면 error.vue 레이아웃에서 전달된 에러 코드와 에러 메시지가 나타나게 된다.
만약 미들웨어가 아니라 컴포넌트나 페이지 단위에서 에러 핸들러를 사용할 경우에는 아래와 같이 활용할 수 있다.
this.$nuxt.error({ statusCode: 404, message: 'Route Error' })
여기서 또 하나의 난관에 부딪혔는데, 팝업이 열려 있는 상태에서 에러가 발생해 에러 페이지로 이동한 경우 팝업이 닫히지 않는 문제가 있었다.
error.vue 컴포넌트가 생성되기 전, 즉 에러 페이지 진입 바로 직전에 열려 있는 팝업들을 닫아야 했다.
미들웨어나 컴포넌트 라이프 사이클 훅을 살펴봤지만 원하는 대로 작동하지 않아 찾아보니, nuxt.config.js에서 제어가 가능했다.
export default {
vue: {
config: {
errorHandler: (error, vm, info) => {
// erorr 이동전 아래 로직 수행 ...
}
}
},
...
}
위와 같이 정의하면 에러 페이지 진입 전에 위의 errorHandler가 먼저 실행된다.
이렇게 error.vue 레이아웃을 이용하면 아주 쉽게 에러 페이지를 컨트롤할 수 있다.