핵심 요약
Vue 4.0(2026-05 RC)은 Virtual DOM을 거치지 않는 Vapor 모드를 기본 모드로 승격했다. 컴파일 타임에 DOM 명령을 직접 생성한다는 점에서 Solid·Svelte 모델에 가깝지만, 기존 Vue SFC 문법을 그대로 사용한다는 차별점이 있다.
1. Vapor가 만드는 코드
입력 SFC
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
3.x 출력 (Virtual DOM)
// 매 렌더마다 vnode 트리를 만들고 diff
function render() {
return h('button', { onClick: () => count.value++ }, count.value)
}
4.0 Vapor 출력
// 컴파일 타임에 직접 DOM 명령으로
const t0 = template('<button></button>')
function setup() {
const count = ref(0)
const n0 = t0()
on(n0, 'click', () => count.value++)
renderEffect(() => setText(n0, count.value))
return n0
}
2. 성능이 왜 개선되나
| 지표 | Virtual DOM | Vapor |
|---|---|---|
| 최소 번들 (mini app) | 34KB | 13KB |
| 초기 렌더 (10k 노드) | 140ms | 52ms |
| 업데이트 (단일 prop 변경) | 78ms | 22ms |
| 메모리 | 기준 | -38% |
핵심은 "필요한 노드만 정확히 업데이트". 반응성 시스템(renderEffect)이 어떤 텍스트·속성이 어떤 ref에 의존하는지 추적해 해당 노드에만 명령을 보낸다.
3. 활성화
npm i vue@^4.0.0-rc.1
// vite.config.ts
import vue from '@vitejs/plugin-vue'
export default {
plugins: [vue({ features: { vapor: true } })],
}
점진 도입 — 컴포넌트 단위
<script setup vapor>
// 이 컴포넌트만 Vapor로 컴파일
</script>
4. 호환성 매트릭스
| 기능 | Vapor |
|---|---|
| Composition API (script setup) | O |
| Options API | 제한 (deprecated) |
| Pinia / Vue Router | O |
| Vue Devtools | O (4.0) |
| SSR (renderToString) | O (4.0 RC1+) |
| Suspense | O |
| defineCustomElement | O |
| v-skip / Transition | O |
| Render function (h()) | 제한 (Vapor 외부에선 OK) |
5. 마이그레이션 함정
① Render function 사용 컴포넌트
JSX·h()·동적 render 함수를 쓰는 컴포넌트는 Vapor로 변환되지 않는다. 그대로 Virtual DOM으로 컴파일됨. 한 앱 안에 두 모드가 공존 가능하지만 경계에서 약간의 인터롭 비용이 발생.
② 일부 라이프사이클의 의미 차이
onUpdated는 Virtual DOM의 patch 시점을 가리켰다. Vapor에선 의미가 모호 → "컴포넌트 단위 업데이트"라는 개념이 약하므로 비추천.
③ 동적 컴포넌트
<component :is="dynamicComp" />
이 패턴은 작동하지만 컴파일러가 미리 최적화 못 하므로 성능 이점이 줄어든다.
④ 슬롯 함수
Scoped slot에 함수를 직접 전달하는 패턴은 Vapor에선 더 명시적인 형태로 작성 권장.
6. SSR — 무엇이 다른가
Vapor SSR은 hydration이 더 작다. 서버는 HTML + 작은 hydration 매니페스트를 보내고, 클라이언트는 이벤트 리스너만 부착. Resumability에 한 걸음 가까운 모델.
7. Pinia·Router 동작
4.0과 함께 출시된 Pinia 4 / Vue Router 5는 Vapor 친화적 내부 재작성. 기존 사용 코드는 변경 없음.
8. 마이그레이션 단계
- Phase 0: Vue 3.5로 업그레이드 (3.x 최종)
- Phase 1: Volar 3.0·TS 5.5·Vite 7로 도구 체인 갱신
- Phase 2: Vue 4.0 RC 설치·전체 빌드 확인 (Vapor OFF)
- Phase 3: 새 컴포넌트만
script setup vapor - Phase 4: 핫 페이지(트래픽 큰 라우트) Vapor 마이그레이션
- Phase 5: 전역 활성화 — 빌드/번들 사이즈 측정
9. 디버깅
# 컴파일된 코드 보기
npx vue-vapor-explorer App.vue
# 또는 Vue DevTools "Source" 탭 — Vapor 컴포넌트는 별도 마킹
10. 권장 전략
- 신규 프로젝트: Vapor ON으로 시작
- 대형 기존 프로젝트: 점진 도입, 핫 라우트부터
- render function 헤비 코드: 이전 후 Vapor로 변환할지 단계적 결정
참고
- vuejs.org/guide/extras/vapor
- Evan You "Vapor Mode Deep Dive" Vue.js Live 2026

댓글 0