[NuxtJS] 미들웨어(middleware) 사용하기
미들웨어(Middleware)
NuxtJS의 라이프 사이클을 보면 nuxtServerInit 다음에 Route Middleware라는 녀석이 있다.
여기서 미들웨어면 미들웨어지 왜 "라우트 미들웨어"라는 명칭을 사용하냐면 NuxtJS에서는 서버 미들웨어와 라우트 미들웨어 두 종류가 존재하기 때문에 미들웨어라는 명칭보다는 라우트 미들웨어라는 명칭을 사용하는 듯 하다.
(하지만 일반적으로 NuxtJS에서 미들웨어라 하면 라우트 미들웨어를 지칭하기 때문에 그냥 미들웨어로 지칭하도록 하겠다.)
NuxtJS에서 미들웨어는 크게 익명 미들웨어(Anonymous Middleware)와 네임드 미들웨어(Named Middleware)로 나뉜다.
익명 미들웨어(Anonymous Middleware)
익명 미들웨어는 특정 페이지나 레이아웃에 종속되는 미들웨어를 뜻한다.
<template>
<h1>Secret page</h1>
</template>
<script>
export default {
middleware({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>
이런 식으로 페이지나 레이아웃에 직접 middleware를 명시하여 사용하며, 직접적으로 명시하여 사용하기 때문에 다른 곳에서 같이 사용할 수 없는 미들웨어 사용 방식이다.
네임드 미들웨어(Named Middleware)
Nuxt 프로젝트를 진행하다 보면 middleware 디렉토리가 존재하는데,
이 디렉토리에서 여러 페이지나 레이아웃에서 공유될 수 있도록 관리되는 미들웨어를 네임드 미들웨어라고 한다.
// middleware/stats.js
import http from 'http'
export default function ({ route }) {
return http.post('http://my-stats-api.com', {
url: route.fullPath
})
}
이러한 미들웨어가 존재한다면 이 미들웨어를 가지고 "전역 설정" 혹은 "지역 설정"이 가능하다.
전역 설정
전역 설정 시 페이지나 레이아웃에서 미들웨어를 사용하는 게 아니라 nuxt.config.js에 명시하여 사용한다.
// nuxt.config.js
export default {
router: {
middleware: 'stats'
}
}
middleware의 명칭을 stats로 하는 것을 보고 하나 알 수 있는 점이 있는데,
middleware 디렉토리 안에 명시된 파일명을 그대로 따라간다는 것을 알 수 있다.
이렇게 전역 설정을 해둔다면 stats 미들웨어는 라우트가 변경될 때마다 실행될 것이다.
지역 설정
지역 설정은 익명 미들웨어와 마찬가지로 적용하고 싶은 페이지나 레이아웃에 미들웨어를 명시해 주면 된다.
// pages/index.vue
// layouts/default.vue
export default {
middleware: ['stats']
}
여기서 짚고 넘어가야 할 부분이 두 개가 있는데,
첫 번째는 우선 nuxt2 공식문서를 살펴보면 위 예제들은 "라우터 미들웨어"라는 명칭으로 설명되어 있다는 점과
두 번째는 미들웨어는 하나만 사용할 수 있는 게 아니라 여러 개 사용 가능하면 그럴 때는 배열 안에 나열해 주면 된다는 것이다.
왜 공식문서에서 라우터 미들웨어라고 따로 설명했는지는 모르겠다.
지역 설정으로는 pages/index.vue, layouts/default.vue 뿐만 아니라 페이지와 레이아웃에서 전체적으로 사용이 가능하다.
또 다른 예제를 보자면 만약 사용자 인증이 필요하다 하면 인증 미들웨어를 하나 만들어주고
// middleware/authenticated.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
이 사용자 인증이 필요한 페이지나 레이아웃에서 사용해주기만 하면 된다.
<template>
<h1>Secret page</h1>
</template>
<script>
export default {
middleware: 'authenticated'
}
</script>
몇 가지 인수를 받는 걸까?
지금까지 예제를 살펴보면 미들웨어는 store/ redirect/ route 등 여러 가지 인수를 받아 사용이 가능한 것으로 보인다.
저 인수들을 담고 있는 객체는 nuxt에서는 당연히 "context"를 의미한다.
context객체는 nuxt에서 자주 사용되는 객체 인수로 이런 걸 쓸 수 있고 이런 곳들에서 받아 사용할 수 있구나 정도만 한번 알고 넘어가 주면 좋을 듯싶다.
export default function (context) {
// Add the userAgent property to the context
context.userAgent = process.server
? context.req.headers['user-agent']
: navigator.userAgent
}
다른 예제들은 context 인수에서 필요한 것만 명시해서 사용해 준 것뿐이다.
그리고 미들웨어 역시 실행 순서가 존재하는데 다음과 같은 순서로 실행된다.
- nuxt.config.js
- Matched layouts
- Matched pages
Nuxt3에서의 미들웨어 변경사항은?
자 그렇다면 Nuxt3에서는 과연 어떻게 바뀌었을까?
Nuxt3는 내가 알기론 Vue3 마냥 Options API와 Composition API를 선택하여 사용할 수 없는 것으로 알고 있고 Composition API를 기반으로 만들었기 때문에 많이 바뀌었을 것이라고 추측할 수 있다.
우선 전체적인 미들웨어 포맷이 바뀌었다.
export default defineNuxtRouteMiddleware((to, from) => {
if (to.params.id === '1') {
return abortNavigation()
}
return navigateTo('/')
})
우선 defineNuxtRouteMiddleware를 사용하며 인수로는 Nuxt2와 다르게 context가 아니라 라우트 인수인 to/from을 받아서 사용할 수 있다.
그렇담 context를 사용할 수 없는 걸까?
나도 아직 Nuxt3에서 미들웨어를 사용해보지 않았지만 composition API에는 useContext가 있다는 것을 잊지 말자.
그리고 특이한 점은 두 개의 함수를 제공하는데 바로 navigateTo와 abortNavigation이다.
함수명만 가지고도 어느 정도 기능이 유추가 가능한데,
navigateTo는 라우트에서 이동하는 것과 마찬가지로 동일하게 이동시키는 것이다.
abortNavigation은 말 그대로 취소시키는 것이다.
좀 더 자세히 알고 싶다면 Nuxt3의 공식문서를 찾아보는 것을 추천한다.
그리고 플러그인에서 미들웨어를 동적으로 생성할 수 있는 기능이 생겼다.
export default defineNuxtPlugin(() => {
addRouteMiddleware('global-test', () => {
console.log('this global middleware was added in a plugin and will be run on every route change')
}, { global: true })
addRouteMiddleware('named-test', () => {
console.log('this named middleware was added in a plugin and would override any existing middleware of the same name')
})
})
사실 defineNuxtPlugin이라는 함수는 미들웨어용으로만 사용되는 게 아니라 플러그인에서 제공하는 함수인데 거기서 미들웨어를 동적으로 추가할 수 있다고 안내하는 것으로 보인다.
자 마지막으로 이 미들웨어를 사용하는 방법 역시 바뀌는 것을 피해 갈 수 없었다.
<script setup>
definePageMeta({
middleware: ["auth"]
// or middleware: 'auth'
})
</script>
Vue3의 script setup에서 이런 식으로 사용할 수 있나 보다.
여기까지 Nuxt3에서 크게 바뀌는 부분들을 알아보았는데,
미들웨어라는 것의 컨셉이 크게 바뀐 것은 없고 단순히 사용 방법만 바뀐 것뿐이니 크게 어려운 부분은 없어 보인다.
그래도 역시 공.식.문.서를 꼭 살펴보길 바란다.
참고: https://nuxtjs.org/docs/directory-structure/middleware/
참고: https://nuxt.com/docs/guide/directory-structure/middleware