라우팅
라우팅 (Routing)
Nuxt의 가장 큰 특징 중 하나가 파일 시스템 라우팅이에요. app/pages/ 디렉터리 안에 Vue 파일을 하나 만들면, 그 파일 이름에 해당하는 URL(경로)이 자동으로 생깁니다. 경로를 별도로 등록하는 라우터 설정 없이, 페이지 파일을 만들고 지우는 것만으로 화면 전환이 정리되는 구조예요.
출처: 공식문서
본문
Nuxt는 파일 시스템 라우터를 써서 app/pages/ 디렉터리의 모든 Vue 파일이 대응하는 URL(route)을 만들게 해요. 각 페이지를 동적 임포트(dynamic import)로 불러오면서 코드 스플리팅(code-splitting)을 활용해, 요청된 경로에 필요한 만큼만 최소한의 자바스크립트를 전달하죠.
코드 스플리팅은 기본으로 켜져 있고 대부분의 앱에서 권장돼요. 굳이 단일 번들로 묶어야 할 이유가 있다면 nuxt.config에서 끌 수 있는데, 보통은 이득보다 초기 다운로드가 커져서 권장하지 않아요. 정말 도움이 된다고 측정했을 때만 꺼보세요.
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
$client: {
build: {
rolldownOptions: {
output: {
codeSplitting: false,
},
},
},
},
},
})
Pages
Nuxt 라우팅은 vue-router를 바탕으로 하고, app/pages/ 디렉터리에 만든 컴포넌트의 파일 이름을 기준으로 경로를 생성해요. 이 파일 시스템 라우팅은 이름 규칙을 이용해 동적·중첩 경로를 만들어 줘요.
-| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
Navigation
<NuxtLink> 컴포넌트가 페이지 사이를 이어줘요. 내부적으로 <a> 태그를 렌더링하는데, href는 해당 페이지의 경로로 설정되죠. 앱이 하이드레이션된 뒤에는 페이지 전환이 자바스크립트로 일어나서 브라우저 URL만 바뀌고, 전체 새로고침 없이 애니메이션 전환이 가능해요.
또 클라이언트에서 <NuxtLink>가 뷰포트에 들어오면, Nuxt가 연결된 페이지의 컴포넌트와 페이로드(생성된 페이지)를 미리 가져와서(prefetch) 더 빠르게 이동하게 도와줘요.
<!-- app/pages/index.vue -->
<template>
<header>
<nav>
<ul>
<li><NuxtLink to="/about">About</NuxtLink></li>
<li><NuxtLink to="/posts/1">Post 1</NuxtLink></li>
<li><NuxtLink to="/posts/2">Post 2</NuxtLink></li>
</ul>
</nav>
</header>
</template>
Route Parameters
현재 경로 정보는 useRoute() 컴포저블로 접근해요. <script setup> 블록이나 Vue 컴포넌트의 setup() 메서드에서 쓸 수 있어요.
<!-- pages/posts/[id].vue -->
<script setup lang="ts">
const route = useRoute()
// /posts/1 에 접근하면 route.params.id 는 1
console.log(route.params.id)
</script>
Route Middleware
Nuxt는 특정 경로로 이동하기 전에 실행할 코드를 빼내기 좋은, 커스터마이즈 가능한 라우트 미들웨어 프레임워크를 제공해요. 이름이 비슷해서 헷갈리기 쉬운데, 이 라우트 미들웨어는 Vue 부분에서 돌아가며 서버에서 도는 Nitro 서버 미들웨어와는 완전히 달라요. 라우트 미들웨어는 서버 경로(예: /api/*)나 다른 서버 요청에는 돌지 않으니, 그런 요청에는 서버 미들웨어를 쓰세요.
라우트 미들웨어는 세 가지 종류가 있어요.
- 익명(인라인) 미들웨어 — 사용하는 페이지 안에 직접 정의
- 이름 있는 미들웨어 —
app/middleware/디렉터리에 두고, 페이지에서 쓰일 때 비동기 임포트로 자동 로드. 이름은 kebab-case로 정규화되어someMiddleware는some-middleware가 돼요 - 전역 미들웨어 —
app/middleware/디렉터리에.global접미사를 붙여 두면, 모든 경로 변경마다 자동 실행
/dashboard 페이지를 보호하는 auth 미들웨어 예시를 볼게요.
// middleware/auth.ts
function isAuthenticated (): boolean { return false }
// ---cut---
export default defineNuxtRouteMiddleware((to, from) => {
// isAuthenticated() 인증 여부를 확인하는 예시 메서드
if (isAuthenticated() === false) {
return navigateTo('/login')
}
})
Route Validation
경로 검증도 지원해요. 검증하고 싶은 각 페이지에서 definePageMeta()의 validate 속성을 쓰면 돼요. validate는 route를 인자로 받고, 이 페이지로 렌더링해도 되는 경로인지를 판단한 불리언 값을 돌려줘요. false를 돌려주면 404 에러가 나고, status/statusText가 담긴 객체를 직접 돌려주면 반환할 에러를 커스터마이즈할 수도 있어요. 더 복잡한 케이스라면 익명 라우트 미들웨어를 쓰면 돼요.
<!-- pages/posts/[id].vue -->
<script setup lang="ts">
definePageMeta({
validate (route) {
// id 가 숫자로만 이뤄졌는지 확인
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
},
})
</script>
더 알아보기
- Pages · Middleware 등 파일 구조에 대한 내용은 Directory Structure 문서에서 다뤄요
<NuxtLink>와useRoute(),definePageMeta()의 세부 옵션은 API 문서를 참고하세요