[Nuxt 2 개발 서버 시작 흐름]
모든 소스 파일
↓
webpack - 전체 의존성 그래프 분석
↓
모듈 번들링 (vendor, app 분리)
↓
메모리에 번들 유지
↓
개발 서버 시작 ← 이 시점에 HMR 가능[Nuxt 3 개발 서버 시작 흐름]
개발 서버 즉시 시작 ← 번들링 없음
↓
브라우저 요청 발생
↓
요청된 파일만 개별 변환 (on-demand)
↓
ESM import로 브라우저에 전달
.nuxt/
imports.d.ts ← auto-import 타입 선언
components.d.ts ← components/ 타입 선언
nuxt.d.ts ← Nuxt 전역 타입
types/
schema.d.ts ← nuxt.config 타입
nitro.d.ts ← Nitro 서버 타입// .nuxt/imports.d.ts (자동 생성됨)
export {}
declare global {
const ref: typeof import('vue')['ref']
const computed: typeof import('vue')['computed']
const useState: typeof import('#app')['useState']
const useFetch: typeof import('#app')['useFetch']
const useRoute: typeof import('#app')['useRoute']
// ... composables/ 안의 파일들도 여기 추가됨
}
[서버]
1. 라우트 매칭
2. asyncData(context) 실행
- context.params, context.$axios 등 사용
- 반환값 = { post: {...} }
3. 반환값을 컴포넌트 data()와 병합
4. 컴포넌트 렌더링 (SSR)
5. HTML 생성 + window.__NUXT__ 인라인 삽입
[HTML 예시]
<script>
window.__NUXT__ = {
data: [{ post: { id: 1, title: "Hello" } }],
state: { /* Vuex state */ }
}
</script>
[클라이언트]
6. window.__NUXT__.data[0]을 읽어서 컴포넌트 data 복원
7. hydration 완료 (asyncData 재실행 없음)
export default {
async asyncData({ params, $axios }) {
// ↑ 컴포넌트 인스턴스가 아닌 context 객체를 받음
const post = await $axios.$get(`/api/posts/${params.id}`)
return { post } // ← 반환값이 data()와 자동 병합됨
},
data() {
return {
post: null, // asyncData 실행 전 초기값
}
},
}async asyncData({ params, query, store, $axios, redirect, error }) {
// params ← 라우트 파라미터
// query ← 쿼리스트링
// store ← Vuex store
// $axios ← nuxtjs/axios 모듈 (설치한 경우)
// redirect ← 다른 경로로 리다이렉트
// error ← 에러 페이지 표시
} export default {
// asyncData: 컴포넌트 생성 전 실행, this 없음, 반환값이 data에 병합
async asyncData({ $axios, params }) {
const post = await $axios.$get(`/api/posts/${params.id}`)
return { post }
},
// fetch: 컴포넌트 생성 후 실행, this 있음, 반환값 없음
async fetch() {
this.comments = await this.$axios.$get(`/api/comments`)
// this.$fetchState.pending, this.$fetchState.error 로 상태 접근 가능
},
data() {
return {
post: null,
comments: [],
}
},
}[서버]
1. <script setup> 실행 시작
2. useFetch('/api/posts', { key: 'posts' }) 호출
- key = 'posts'로 캐시 식별
- 서버에서 $fetch('/api/posts') 실행
- Nitro가 내부 라우트 감지 → 네트워크 없이 직접 핸들러 호출
3. 응답 데이터를 payload에 저장
- useNuxtApp().payload.data['posts'] = { ... }
4. HTML 렌더링
[HTML 예시]
<script type="application/json" id="__NUXT_DATA__">
{ "posts": [{ "id": 1, "title": "Hello" }] }
</script>
[클라이언트]
5. #__NUXT_DATA__ 파싱
6. useFetch('/api/posts', { key: 'posts' }) 호출
- payload.data['posts'] 확인 → 캐시 hit
- 네트워크 요청 없이 캐시에서 data 반환
7. hydration 완료
// Nuxt 2 서버 내부 (단순화)
const connect = require('connect')
const app = connect()
app.use(nuxtMiddleware) // SSR 처리
app.use(serverMiddleware) // 사용자 정의 미들웨어
http.createServer(app).listen(3000)// Nitro 핸들러 추상화 (단순화)
interface H3Event {
node?: { req: IncomingMessage, res: ServerResponse } // Node.js
cloudflare?: { request: Request } // Cloudflare Workers
deno?: { request: Request } // Deno
// ...
}
export default defineEventHandler((event: H3Event) => {
// 어떤 런타임이든 같은 인터페이스로 처리
const body = await readBody(event) // H3 헬퍼 사용
return { ok: true }
})
[nuxt build --preset cloudflare-pages]
소스 코드 (H3 기반)
↓
Rollup 번들링
↓
Cloudflare Workers 어댑터 적용 ← preset이 결정
↓
_worker.js (Cloudflare Workers 포맷)
[nuxt build --preset node-server]
↓
Node.js 어댑터 적용
↓
server/index.mjs (Node.js 서버)// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
preset: 'cloudflare-pages', // 이것만 바꾸면 배포 환경 전환
},
})// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // 빌드 시 HTML 정적 생성
'/blog/**': { swr: 3600 }, // Stale-While-Revalidate
'/admin/**': { ssr: false }, // SPA
'/api/**': { cors: true }, // CORS 헤더 추가
},
})[SWR 동작 흐름]
첫 요청 (캐시 없음)
→ 서버 렌더링 → 캐시 저장 → HTML 반환
3600초 이내 재요청
→ 캐시 hit → 즉시 HTML 반환 (렌더링 없음)
3600초 경과 후 재요청
→ 캐시 stale 판정 → 캐시 HTML 즉시 반환 (사용자 대기 없음)
→ 백그라운드에서 서버 재렌더링 → 캐시 갱신
항목 | Nuxt 2 | Nuxt 3 |
Vue 버전 | Vue 2 | Vue 3 |
컴포넌트 스타일 | Options API | Composition API + <script setup> |
빌드 도구 | webpack 4/5 | Vite (dev) + Rollup (prod) |
서버 엔진 | Connect | Nitro (H3 기반) |
데이터 페칭 | asyncData, fetch 옵션 | useFetch, useAsyncData composable |
SSR payload 전달 | window.__NUXT__ (인덱스 기반) | #__NUXT_DATA__ JSON (키 기반) |
상태 관리 | Vuex (내장) | Pinia + useState |
API 라우트 | serverMiddleware | server/api/ (Nitro 자동 등록) |
동적 라우트 파일명 | _id.vue (언더스코어) | [id].vue (대괄호) |
TypeScript | @nuxt/typescript-build 별도 설치 | 기본 지원 |
Auto-import 범위 | components/ (선택적) | components, composables, utils 전체 |
렌더링 단위 | 앱 전체 | 라우트별 (routeRules) |
배포 환경 | Node.js 종속 | preset으로 다중 런타임 지원 |
메타 태그 | head() 컴포넌트 옵션 | useHead(), useSeoMeta() composable |
설정 파일 | nuxt.config.js (JS/CJS) | nuxt.config.ts (TypeScript) |
npm install -D @nuxt/bridge # Nuxt 2 위에서 Nuxt 3 API 일부 사용 가능