# 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
```
부모 레이아웃이 있다면 ``로 자식 라우트를 렌더링.
---
## 네비게이션
### ``
뷰포트에 들어오면 자동으로 다음 페이지 컴포넌트와 payload를 프리패치. 전체 페이지 새로고침 없이 클라이언트 사이드 라우팅.
```vue
```
### `navigateTo()` — 프로그래매틱 이동
```typescript
// 미들웨어나 이벤트 핸들러에서
await navigateTo('/login')
await navigateTo({ path: '/search', query: { q: 'nuxt' } })
await navigateTo('https://external.com', { external: true })
```
---
## 라우트 파라미터
```vue
```
---
## 라우트 미들웨어
> ⚠️ 주의: 라우트 미들웨어는 Vue 앱의 클라이언트/서버 파트에서 실행됨. Nitro 서버의 `server/middleware/`와 다름. API 라우트(`/api/*`)에는 동작하지 않음.
### 종류 3가지
| 종류 | 위치 | 적용 범위 |
|---|---|---|
| **Global** | `middleware/auth.global.ts` | 모든 라우트 변경 |
| **Named** | `middleware/auth.ts` | 지정한 페이지만 |
| **Anonymous** | 페이지 컴포넌트 안 | 해당 페이지만 |
### Named 미들웨어 예시
```typescript
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const user = useUser()
if (!user.value) {
return navigateTo('/login')
}
})
```
```vue
```
### Anonymous(Inline) 미들웨어
```vue
```
### 미들웨어에서 실행 흐름 제어
```typescript
export default defineNuxtRouteMiddleware((to, from) => {
// 계속 진행
return
// 다른 페이지로 리다이렉트
return navigateTo('/login')
// 현재 라우트 abort (404 표시)
return abortNavigation()
// 커스텀 에러
return abortNavigation({ statusCode: 403, message: 'Forbidden' })
})
```
---
## 라우트 검증 (validate)
```vue
```
---
## `definePageMeta` 주요 옵션
```typescript
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.md`
- `reference/2.directory-structure/1.app/1.middleware.md`
- `reference/2.directory-structure/1.app/1.pages.md`