- CLAUDE.md 운영 규칙 - wiki/ 정리된 지식 페이지 (Nuxt + Claude Code) - raw/ 원본 자료 - reference/ Nuxt 4.x 공식 문서 Co-authored-by: Cursor <cursoragent@cursor.com>
4.6 KiB
4.6 KiB
Nuxt 라우팅
카테고리: 핵심 개념 최종 수정: 2026-05-13 관련: nuxt-lifecycle, nuxt-rendering-modes
요약
Nuxt는 app/pages/ 디렉토리의 파일 구조를 기반으로 vue-router 라우트를 자동 생성한다. 동적 라우트, 중첩 라우트, 미들웨어를 파일 네이밍 컨벤션만으로 설정한다.
파일 기반 라우팅
pages/
├── index.vue → /
├── about.vue → /about
└── posts/
├── index.vue → /posts
└── [id].vue → /posts/:id
💡 경험:
pages/디렉토리가 없으면 Nuxt는 vue-router를 포함하지 않음 (app.vue 단독 사용 가능).
라우트 파일 네이밍 패턴
| 파일명 | 라우트 | 설명 |
|---|---|---|
pages/index.vue |
/ |
루트 |
pages/about.vue |
/about |
정적 라우트 |
pages/posts/[id].vue |
/posts/:id |
동적 파라미터 |
pages/[...slug].vue |
/* |
Catch-all |
pages/[[optional]].vue |
/ 또는 /:optional |
선택적 파라미터 |
pages/user-[group]/[id].vue |
/user-:group/:id |
복합 동적 |
중첩 라우트
pages/
└── parent/
├── index.vue → /parent
└── child.vue → /parent/child
부모 레이아웃이 있다면 <NuxtPage />로 자식 라우트를 렌더링.
네비게이션
<NuxtLink>
뷰포트에 들어오면 자동으로 다음 페이지 컴포넌트와 payload를 프리패치. 전체 페이지 새로고침 없이 클라이언트 사이드 라우팅.
<template>
<nav>
<NuxtLink to="/">홈</NuxtLink>
<NuxtLink to="/about">소개</NuxtLink>
<NuxtLink :to="{ name: 'posts-id', params: { id: 1 } }">포스트 1</NuxtLink>
</nav>
</template>
navigateTo() — 프로그래매틱 이동
// 미들웨어나 이벤트 핸들러에서
await navigateTo('/login')
await navigateTo({ path: '/search', query: { q: 'nuxt' } })
await navigateTo('https://external.com', { external: true })
라우트 파라미터
<script setup lang="ts">
const route = useRoute()
// /posts/123 접근 시
console.log(route.params.id) // '123'
console.log(route.query.page) // 쿼리스트링
console.log(route.fullPath) // '/posts/123?page=1'
</script>
라우트 미들웨어
⚠️ 주의: 라우트 미들웨어는 Vue 앱의 클라이언트/서버 파트에서 실행됨. Nitro 서버의
server/middleware/와 다름. API 라우트(/api/*)에는 동작하지 않음.
종류 3가지
| 종류 | 위치 | 적용 범위 |
|---|---|---|
| Global | middleware/auth.global.ts |
모든 라우트 변경 |
| Named | middleware/auth.ts |
지정한 페이지만 |
| Anonymous | 페이지 컴포넌트 안 | 해당 페이지만 |
Named 미들웨어 예시
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const user = useUser()
if (!user.value) {
return navigateTo('/login')
}
})
<!-- pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
middleware: 'auth', // 단일
// middleware: ['auth', 'verified'], // 복수
})
</script>
Anonymous(Inline) 미들웨어
<script setup lang="ts">
definePageMeta({
middleware: defineNuxtRouteMiddleware((to, from) => {
// 이 페이지 전용 로직
}),
})
</script>
미들웨어에서 실행 흐름 제어
export default defineNuxtRouteMiddleware((to, from) => {
// 계속 진행
return
// 다른 페이지로 리다이렉트
return navigateTo('/login')
// 현재 라우트 abort (404 표시)
return abortNavigation()
// 커스텀 에러
return abortNavigation({ statusCode: 403, message: 'Forbidden' })
})
라우트 검증 (validate)
<script setup lang="ts">
definePageMeta({
validate(route) {
// id가 숫자인지 확인
return /^\d+$/.test(route.params.id as string)
// false → 404
// { status: 403 } → 커스텀 에러
},
})
</script>
definePageMeta 주요 옵션
definePageMeta({
layout: 'dashboard', // 레이아웃 지정
middleware: ['auth'], // 미들웨어
validate: (route) => true, // 라우트 검증
keepalive: true, // 컴포넌트 캐싱
pageTransition: { name: 'slide', mode: 'out-in' }, // 페이지 트랜지션
key: route => route.fullPath, // 컴포넌트 key 제어
})
참고 / 출처
reference/1.getting-started/07.routing.mdreference/2.directory-structure/1.app/1.middleware.mdreference/2.directory-structure/1.app/1.pages.md