middleware
Nuxt는 애플리케이션 전반에서 사용할 수 있는 라우트 미들웨어 프레임워크를 제공하며, 특정 라우트로 이동하기 전에 실행하고 싶은 코드를 추출하는 데 이상적입니다.
라우트 미들웨어에는 세 가지 종류가 있습니다:
- 익명(또는 인라인) 라우트 미들웨어는 페이지 내에서 직접 정의됩니다.
middleware/에 위치한 이름 있는 라우트 미들웨어는 페이지에서 사용될 때 비동기 임포트로 자동 로드됩니다.middleware/에.global접미사가 붙은 전역 라우트 미들웨어는 모든 라우트 변경 시 실행됩니다.
첫 번째와 두 번째 종류의 라우트 미들웨어는 definePageMeta에서 정의할 수 있습니다.
myMiddleware는 my-middleware가 됩니다.사용법
라우트 미들웨어는 현재 라우트와 다음 라우트를 인자로 받는 내비게이션 가드입니다.
export default defineNuxtRouteMiddleware((to, from) => {
if (to.params.id === '1') {
return abortNavigation()
}
// 실제 앱에서는 모든 라우트를 `/`로 리다이렉트하지 않을 것입니다
// 하지만 리다이렉트 전에 반드시 `to.path`를 확인해야 하며
// 그렇지 않으면 무한 리다이렉트 루프에 빠질 수 있습니다
if (to.path !== '/') {
return navigateTo('/')
}
})
Nuxt는 미들웨어에서 직접 반환할 수 있는 두 가지 전역 헬퍼를 제공합니다.
navigateTo- 지정한 라우트로 리다이렉트합니다abortNavigation- 내비게이션을 중단하며, 선택적으로 에러 메시지를 전달할 수 있습니다.
navigation guards와는 달리, vue-router의 세 번째 인자인 next()는 전달되지 않으며, 리다이렉트 또는 라우트 취소는 미들웨어에서 값을 반환함으로써 처리됩니다.
가능한 반환 값은 다음과 같습니다:
- 아무것도 반환하지 않음(단순히
return또는 반환문 없음) - 내비게이션을 차단하지 않으며, 다음 미들웨어 함수(있다면)로 이동하거나 라우트 내비게이션을 완료합니다 return navigateTo('/')- 지정한 경로로 리다이렉트하며, 서버 측에서 리다이렉트가 발생하면 리다이렉트 코드를302Found로 설정합니다return navigateTo('/', { redirectCode: 301 })- 지정한 경로로 리다이렉트하며, 서버 측에서 리다이렉트가 발생하면 리다이렉트 코드를301Moved Permanently로 설정합니다return abortNavigation()- 현재 내비게이션을 중단합니다return abortNavigation(error)- 현재 내비게이션을 에러와 함께 거부합니다
미들웨어 실행 순서
미들웨어는 다음 순서로 실행됩니다:
- 전역 미들웨어
- 페이지에서 정의된 미들웨어 순서(배열 문법으로 여러 개 선언된 경우)
예를 들어, 다음과 같은 미들웨어와 컴포넌트가 있다고 가정해봅시다:
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// 커스텀 인라인 미들웨어
},
'auth',
],
});
</script>
미들웨어는 다음과 같은 순서로 실행됩니다:
analytics.global.tssetup.global.ts- 커스텀 인라인 미들웨어
auth.ts
전역 미들웨어 순서 지정
기본적으로 전역 미들웨어는 파일 이름을 기준으로 알파벳 순서대로 실행됩니다.
하지만 특정 순서로 실행하고 싶을 때가 있을 수 있습니다. 예를 들어, 위의 예시에서 setup.global.ts가 analytics.global.ts보다 먼저 실행되어야 할 수 있습니다. 이 경우, 전역 미들웨어 파일 이름 앞에 '알파벳' 번호를 붙이는 것을 권장합니다.
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
10.new.global.ts가 2.new.global.ts보다 먼저 올 수 있습니다. 그래서 예시에서는 한 자리 숫자 앞에 0을 붙였습니다.미들웨어가 실행되는 시점
사이트가 서버 렌더링되거나 정적으로 생성된 경우, 초기 페이지의 미들웨어는 페이지가 렌더링될 때와 클라이언트에서 다시 한 번 실행됩니다. 미들웨어가 브라우저 환경을 필요로 할 때(예: 정적 사이트, 응답을 적극적으로 캐시, local storage에서 값을 읽고 싶을 때) 이 동작이 필요할 수 있습니다.
하지만 이 동작을 피하고 싶다면 다음과 같이 할 수 있습니다:
export default defineNuxtRouteMiddleware(to => {
// 서버에서 미들웨어 건너뛰기
if (import.meta.server) return
// 클라이언트에서 미들웨어 완전히 건너뛰기
if (import.meta.client) return
// 또는 클라이언트의 초기 로드에서만 미들웨어 건너뛰기
const nuxtApp = useNuxtApp()
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
이것은 서버에서 미들웨어에서 에러를 throw하여 에러 페이지가 렌더링되는 경우에도 마찬가지입니다. 미들웨어는 브라우저에서 다시 실행됩니다.
useError를 사용할 수 있습니다.미들웨어 동적 추가
addRouteMiddleware() 헬퍼 함수를 사용하여 플러그인 등에서 전역 또는 이름 있는 라우트 미들웨어를 수동으로 추가할 수 있습니다.
export default defineNuxtPlugin(() => {
addRouteMiddleware('global-test', () => {
console.log('이 전역 미들웨어는 플러그인에서 추가되었으며, 모든 라우트 변경 시 실행됩니다')
}, { global: true })
addRouteMiddleware('named-test', () => {
console.log('이 이름 있는 미들웨어는 플러그인에서 추가되었으며, 동일한 이름의 기존 미들웨어를 덮어씁니다')
})
})
예시
-| middleware/
---| auth.ts
페이지 파일에서 이 라우트 미들웨어를 참조할 수 있습니다:
<script setup lang="ts">
definePageMeta({
middleware: ["auth"]
// 또는 middleware: 'auth'
})
</script>
이제 해당 페이지로 이동이 완료되기 전에 auth 라우트 미들웨어가 실행됩니다.
빌드 타임에 미들웨어 설정하기
각 페이지에서 definePageMeta를 사용하는 대신, pages:extend 훅 내에서 이름 있는 라우트 미들웨어를 추가할 수 있습니다.
import type { NuxtPage } from 'nuxt/schema'
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
function setMiddleware (pages: NuxtPage[]) {
for (const page of pages) {
if (/* 어떤 조건 */ true) {
page.meta ||= {}
// 이 코드는 페이지 내의 `definePageMeta`에서 설정한 미들웨어를 덮어쓴다는 점에 유의하세요
page.meta.middleware = ['named']
}
if (page.children) {
setMiddleware(page.children)
}
}
}
setMiddleware(pages)
}
}
})