Nuxt 3 Complete Guide | Full-Stack Vue.js Framework
이 글의 핵심
Nuxt 3 is the full-stack Vue.js framework — file-based routing, server routes, composables, and automatic SSR/SSG. This guide covers the Nuxt 3 ecosystem with practical examples for building production apps.
What This Guide Covers
Nuxt 3 brings full-stack capabilities to Vue — file-based routing, server API routes, universal data fetching, and automatic SSR/SSG. This guide covers the core features with a practical blog/app example.
Real-world insight: Migrating a Vue SPA to Nuxt 3 cut Time to First Byte by 70% and improved Core Web Vitals scores enough to boost organic traffic by 40% in two months.
Setup
npx nuxi@latest init my-app
cd my-app
npm install
npm run dev
App runs on http://localhost:3000.
Project Structure
my-app/
pages/ ← file-based routing
components/ ← auto-imported components
composables/ ← auto-imported composables (useX)
server/
api/ ← server API routes
middleware/ ← server middleware
layouts/ ← page layouts
middleware/ ← client/universal route middleware
plugins/ ← Nuxt plugins
public/ ← static assets
nuxt.config.ts
1. File-Based Routing
Create files in pages/ — Nuxt generates routes automatically:
pages/
index.vue → /
about.vue → /about
blog/
index.vue → /blog
[slug].vue → /blog/:slug
users/
[id]/
index.vue → /users/:id
posts.vue → /users/:id/posts
[...404].vue → catch-all / 404
<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
</script>
<template>
<article>
<h1>{{ post?.title }}</h1>
<p>{{ post?.body }}</p>
</article>
</template>
2. Server Routes (API)
Create files in server/api/ — Nuxt generates server endpoints:
// server/api/posts/index.get.ts
export default defineEventHandler(async (event) => {
// Access DB, external API, etc.
return [
{ id: 1, title: 'Nuxt 3 Guide', slug: 'nuxt-3-guide' },
{ id: 2, title: 'Vue Composables', slug: 'vue-composables' },
]
})
// server/api/posts/[slug].get.ts
export default defineEventHandler(async (event) => {
const slug = getRouterParam(event, 'slug')
// Fetch from DB...
return { id: 1, title: 'Nuxt 3 Guide', slug, body: '...' }
})
// server/api/posts/index.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
// Validate and save...
return { created: body }
})
File naming convention: [name].[method].ts — GET, POST, PUT, DELETE, PATCH.
3. Data Fetching
<script setup lang="ts">
// useFetch: SSR-aware, cached, auto-typed
const { data, pending, error, refresh } = await useFetch('/api/posts')
// $fetch: manual fetch (works client and server side)
const post = await $fetch('/api/posts/my-slug')
// useAsyncData: custom async logic
const { data: user } = await useAsyncData('user', () =>
$fetch(`/api/users/${userId}`)
)
// lazy loading (don't block navigation)
const { data: comments, pending } = useLazyFetch('/api/comments')
</script>
<template>
<div>
<div v-if="pending">Loading...</div>
<ul v-else>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
</div>
</template>
useFetch automatically shares data between server and client — no duplicate requests.
4. Composables
Composables in composables/ are auto-imported anywhere in your app:
// composables/useAuth.ts
export function useAuth() {
const user = useState<User | null>('auth-user', () => null)
const isLoggedIn = computed(() => user.value !== null)
async function login(email: string, password: string) {
const data = await $fetch('/api/auth/login', {
method: 'POST',
body: { email, password },
})
user.value = data.user
await navigateTo('/dashboard')
}
async function logout() {
await $fetch('/api/auth/logout', { method: 'POST' })
user.value = null
await navigateTo('/login')
}
return { user, isLoggedIn, login, logout }
}
<script setup lang="ts">
// No import needed — auto-imported
const { user, isLoggedIn, logout } = useAuth()
</script>
5. Layouts
<!-- layouts/default.vue -->
<template>
<div>
<AppHeader />
<main>
<slot /> <!-- page content goes here -->
</main>
<AppFooter />
</div>
</template>
<!-- layouts/dashboard.vue -->
<template>
<div class="dashboard">
<Sidebar />
<main><slot /></main>
</div>
</template>
<!-- pages/dashboard/index.vue -->
<script setup lang="ts">
definePageMeta({ layout: 'dashboard' })
</script>
6. Middleware
// middleware/auth.ts (client + server)
export default defineNuxtRouteMiddleware((to, from) => {
const { isLoggedIn } = useAuth()
if (!isLoggedIn.value && to.path !== '/login') {
return navigateTo('/login')
}
})
<!-- pages/dashboard/index.vue -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
</script>
Server middleware (runs on every request):
// server/middleware/logger.ts
export default defineEventHandler((event) => {
console.log(`[${new Date().toISOString()}] ${event.method} ${event.path}`)
})
7. State Management
Nuxt’s useState shares state between server and client:
// composables/useCounter.ts
export const useCounter = () => useState('counter', () => 0)
<script setup lang="ts">
const count = useCounter()
</script>
<template>
<button @click="count++">Count: {{ count }}</button>
</template>
For complex state, use Pinia (Nuxt’s recommended store):
npx nuxi module add pinia
// stores/cart.ts
export const useCartStore = defineStore('cart', () => {
const items = ref<CartItem[]>([])
const total = computed(() => items.value.reduce((sum, i) => sum + i.price, 0))
function addItem(item: CartItem) {
items.value.push(item)
}
return { items, total, addItem }
})
8. SEO and Meta
<script setup lang="ts">
useSeoMeta({
title: 'My Page Title',
ogTitle: 'My Page Title',
description: 'This is a description of my page.. Nuxt 3 Complete Guide에 대한 완전한 가이드입니다. 실전 예제와 함께 핵심 개념부터 고급 활용까지 다룹니다.',
ogDescription: 'This is a description of my page.',
ogImage: 'https://example.com/image.png',
twitterCard: 'summary_large_image',
})
// Dynamic meta
const { data: post } = await useFetch(`/api/posts/${slug}`)
useSeoMeta({
title: () => post.value?.title,
description: () => post.value?.excerpt,
})
</script>
9. nuxt.config.ts
export default defineNuxtConfig({
// Rendering mode
ssr: true, // SSR (default)
// Nitro server config
nitro: {
preset: 'cloudflare-pages', // or 'vercel', 'netlify', etc.
},
// Runtime config (env vars)
runtimeConfig: {
// Server-only (secret)
databaseUrl: process.env.DATABASE_URL,
// Public (exposed to client)
public: {
apiBase: process.env.API_BASE_URL || '/api',
},
},
// Modules
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss', '@nuxt/image'],
// TypeScript
typescript: { strict: true },
})
Access runtime config:
const config = useRuntimeConfig()
console.log(config.public.apiBase) // client or server
console.log(config.databaseUrl) // server only
10. Deployment
# Build for production
npm run build
# Deploy to Node.js server
node .output/server/index.mjs
# Deploy to Cloudflare Pages
NITRO_PRESET=cloudflare-pages npm run build
# Upload .output/public to Cloudflare Pages
# Static generation (SSG)
npm run generate
# Upload .output/public anywhere (S3, GitHub Pages, etc.)
Key Takeaways
| Feature | How |
|---|---|
| Routing | File-based in pages/ |
| Server API | Files in server/api/ |
| Data fetching | useFetch, useAsyncData, $fetch |
| State | useState (built-in), Pinia (recommended) |
| Auto-imports | components/, composables/ — no imports needed |
| SEO | useSeoMeta() |
| Deployment | Any platform via Nitro presets |
Nuxt 3’s key strength is reducing boilerplate — auto-imports, file-based routing, and built-in SSR mean you focus on features, not configuration. If you know Vue 3, Nuxt 3 is a natural upgrade for any project that needs SEO or a backend.
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Build full-stack apps with Nuxt 3. Covers file-based routing, server routes, composables, Nitro server, data fetching, a… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- The Complete Nuxt 3 Guide | Vue, SSR, Composables, Nitro, Server Routes
- The Complete SvelteKit Guide | Full Stack, Routing, Form Actions, Load, Hooks
- [MCP (Model Context Protocol) Complete Guide](/en/blog/mcp-model-context-protocol-guide/
이 글에서 다루는 키워드 (관련 검색어)
Nuxt, Vue, JavaScript, SSR, Full-Stack, TypeScript 등으로 검색하시면 이 글이 도움이 됩니다.