Nuxt 3 입문
Nuxt 3는 Vue 3 기반의 풀스택 프레임워크로, SSR, SSG, 파일 기반 라우팅, 자동 import 등을 제공합니다. Next.js가 React의 프레임워크라면, Nuxt는 Vue의 프레임워크입니다.
면접에서 "Vue로 SSR을 어떻게 구현하나요?"라고 물으면, Nuxt 3를 활용한 방법과 직접 구현하는 방법을 비교할 수 있으면 좋습니다.
프로젝트 생성
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run dev
프로젝트 구조
my-nuxt-app/
├── .nuxt/ # 빌드 산출물 (gitignore)
├── app.vue # 루트 컴포넌트
├── nuxt.config.ts # Nuxt 설정
├── pages/ # 파일 기반 라우팅
│ ├── index.vue # /
│ ├── about.vue # /about
│ └── users/
│ ├── index.vue # /users
│ └── [id].vue # /users/:id
├── components/ # 자동 import 컴포넌트
├── composables/ # 자동 import composables
├── layouts/ # 레이아웃
├── middleware/ # 라우트 미들웨어
├── plugins/ # 플러그인
├── server/ # 서버 API (Nitro)
│ └── api/
│ └── hello.ts # /api/hello
├── public/ # 정적 파일
└── assets/ # 빌드 시 처리되는 리소스
파일 기반 라우팅
pages/
├── index.vue → /
├── about.vue → /about
├── users/
│ ├── index.vue → /users
│ └── [id].vue → /users/:id (동적)
├── posts/
│ └── [...slug].vue → /posts/a/b/c (catch-all)
└── settings/
└── [[tab]].vue → /settings 또는 /settings/profile (선택적)
<!-- pages/users/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const id = route.params.id // 동적 파라미터
// Nuxt의 자동 import — useRoute를 import하지 않아도 됨
</script>
<template>
<div>사용자 ID: {{ id }}</div>
</template>
자동 Import
Nuxt 3의 가장 편리한 기능입니다. import 문 없이 바로 사용할 수 있습니다.
<script setup lang="ts">
// 이 import들이 전부 불필요!
// import { ref, computed } from 'vue'
// import { useRoute, useRouter } from 'vue-router'
// import { useFetch } from '#app'
const count = ref(0) // Vue API 자동 import
const route = useRoute() // Vue Router 자동 import
const { data } = await useFetch('/api/hello') // Nuxt composable 자동 import
</script>
자동 import 대상:
- Vue API: ref, computed, watch, onMounted 등
- Vue Router: useRoute, useRouter, navigateTo 등
- **composables/ 디렉토리 **: 직접 작성한 composable
- **components/ 디렉토리 **: 모든 컴포넌트
- **utils/ 디렉토리 **: 유틸리티 함수
데이터 가져오기
<script setup lang="ts">
// useFetch — SSR 호환, 자동 키 생성
const { data: users, pending, error, refresh } = await useFetch('/api/users')
// useAsyncData — 커스텀 키와 변환
const { data: post } = await useAsyncData(
`post-${route.params.id}`,
() => $fetch(`/api/posts/${route.params.id}`)
)
// $fetch — 단순 HTTP 요청 (SSR 호환)
const submitForm = async () => {
await $fetch('/api/users', {
method: 'POST',
body: { name: '심정훈' }
})
}
</script>
<template>
<div v-if="pending">로딩 중...</div>
<div v-else-if="error">에러: {{ error.message }}</div>
<ul v-else>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</template>
서버 API (Nitro)
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: '안녕하세요!' }
})
// server/api/users/[id].get.ts — GET /api/users/:id
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id')
return { id, name: `사용자 ${id}` }
})
// server/api/users.post.ts — POST /api/users
export default defineEventHandler(async (event) => {
const body = await readBody(event)
return { created: true, user: body }
})
레이아웃
<!-- layouts/default.vue -->
<template>
<div>
<header>공통 헤더</header>
<main>
<slot />
</main>
<footer>공통 푸터</footer>
</div>
</template>
<!-- pages/admin.vue — 다른 레이아웃 사용 -->
<script setup lang="ts">
definePageMeta({
layout: 'admin'
})
</script>
면접 팁
- Nuxt 3와 Next.js의 공통점(파일 기반 라우팅, SSR, API 라우트)과 차이점(자동 import, Nitro 서버)을 비교할 수 있으면 좋습니다
- 자동 import가 편리하지만, ** 명시적 import를 선호하는 팀도 있다 **는 것을 알고 있으면 실무 감각을 보여줄 수 있습니다
useFetch와$fetch의 차이를 SSR 컨텍스트에서 설명할 수 있어야 합니다
요약
Nuxt 3는 Vue 3 기반의 풀스택 프레임워크로, 파일 기반 라우팅, 자동 import, SSR/SSG 지원, Nitro 서버 엔진을 제공합니다. useFetch로 SSR 호환 데이터 가져오기를, server/api로 백엔드 API를 구현할 수 있습니다.
댓글 로딩 중...