Vue 3.0 주요 특징 및 변경사항
Posted by Albert 67Day 9Hour 26Min 17Sec ago [2025-12-01]
1. Composition API
Vue 3의 가장 큰 변화로, 로직을 재사용 가능한 함수로 구성할 수 있습니다.
// Vue 2 Options API
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
// Vue 3 Composition API
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
2. 반응성 시스템 개선
Proxy 기반의 새로운 반응성 시스템으로 성능이 향상되었습니다.
import { reactive, ref, computed } from 'vue'
export default {
setup() {
// ref: 기본 타입용
const count = ref(0)
// reactive: 객체용
const state = reactive({
name: 'Vue 3',
version: '3.0'
})
// computed: 계산된 속성
const doubleCount = computed(() => count.value * 2)
return { count, state, doubleCount }
}
}
3. setup() 함수
컴포넌트의 진입점으로, Composition API를 사용하는 핵심 함수입니다.
import { ref, onMounted, watch } from 'vue'
export default {
props: ['title'],
setup(props, context) {
const message = ref('Hello')
// 생명주기 훅
onMounted(() => {
console.log('컴포넌트가 마운트되었습니다')
})
// watch를 통한 반응성 추적
watch(() => props.title, (newVal, oldVal) => {
console.log(`제목이 ${oldVal}에서 ${newVal}로 변경됨`)
})
// context.emit으로 이벤트 발생
const handleClick = () => {
context.emit('custom-event', message.value)
}
return {
message,
handleClick
}
}
}
4. Teleport (Portal)
DOM 구조와 상관없이 특정 위치에 컴포넌트를 렌더링할 수 있습니다.
<template>
<div>
<button @click="showModal = true">모달 열기</button>
<!-- body 태그로 텔레포트 -->
<Teleport to="body">
<div v-if="showModal" class="modal">
<p>모달 내용</p>
<button @click="showModal = false">닫기</button>
</div>
</Teleport>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const showModal = ref(false)
return { showModal }
}
}
</script>
5. Fragments (다중 루트 노드)
Vue 3에서는 여러 개의 루트 노드를 가질 수 있습니다.
<template> <!-- Vue 2에서는 에러, Vue 3에서는 정상 동작 --> <header>헤더</header> <main>메인 컨텐츠</main> <footer>푸터</footer> </template>
6. Suspense
비동기 컴포넌트를 처리할 때 로딩 상태를 쉽게 관리할 수 있습니다.
<template>
<Suspense>
<!-- 비동기 컴포넌트 -->
<template 'default>
<AsyncComponent />
</template>
<!-- 로딩 중 표시될 내용 -->
<template 'fallback>
<div>로딩 중...</div>
</template>
</Suspense>
</template>
<script>
import { defineAsyncComponent } from 'vue'
export default {
components: {
AsyncComponent: defineAsyncComponent(() =>
import('./AsyncComponent.vue')
)
}
}
</script>
7. provide/inject 개선
컴포넌트 트리 전체에 데이터를 공유할 수 있습니다.
// 부모 컴포넌트
import { provide, ref } from 'vue'
export default {
setup() {
const theme = ref('dark')
provide('theme', theme)
const changeTheme = () => {
theme.value = theme.value === 'dark' ? 'light' : 'dark'
}
return { changeTheme }
}
}
// 자식 컴포넌트 (깊은 하위 컴포넌트 가능)
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme')
return { theme }
}
}
8. Emits 옵션
컴포넌트가 발생시킬 이벤트를 명시적으로 선언할 수 있습니다.
<template>
<button @click="handleClick">클릭</button>
</template>
<script>
export default {
emits: ['submit', 'cancel'],
setup(props, { emit }) {
const handleClick = () => {
emit('submit', { data: 'example' })
}
return { handleClick }
}
}
</script>
9. Script Setup 구문 (Vue 3.2+)
더 간결한 문법으로 Composition API를 사용할 수 있습니다.
<template>
<div>
<h1>{{ title }}</h1>
<p>카운트: {{ count }}</p>
<button @click="increment">증가</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
// props 정의
const props = defineProps({
title: String
})
// emits 정의
const emit = defineEmits(['update'])
// 반응형 데이터
const count = ref(0)
// 메서드
const increment = () => {
count.value++
emit('update', count.value)
}
// computed
const doubleCount = computed(() => count.value * 2)
</script>
10. 생명주기 훅
Composition API에서의 생명주기 훅 사용법입니다.
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
export default {
setup() {
onBeforeMount(() => {
console.log('마운트 전')
})
onMounted(() => {
console.log('마운트 완료')
})
onBeforeUpdate(() => {
console.log('업데이트 전')
})
onUpdated(() => {
console.log('업데이트 완료')
})
onBeforeUnmount(() => {
console.log('언마운트 전')
})
onUnmounted(() => {
console.log('언마운트 완료')
})
}
}
11. TypeScript 지원 강화
import { defineComponent, ref, PropType } from 'vue'
interface User {
id: number
name: string
}
export default defineComponent({
props: {
user: {
type: Object as PropType<User>,
required: true
}
},
setup(props) {
const count = ref<number>(0)
const message = ref<string>('Hello')
return {
count,
message
}
}
})
12. Composables (재사용 가능한 로직)
// composables/useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const increment = () => count.value++
const decrement = () => count.value--
const reset = () => count.value = initialValue
const doubleCount = computed(() => count.value * 2)
return {
count,
increment,
decrement,
reset,
doubleCount
}
}
// 컴포넌트에서 사용
import { useCounter } from './composables/useCounter'
export default {
setup() {
const { count, increment, decrement, doubleCount } = useCounter(10)
return {
count,
increment,
decrement,
doubleCount
}
}
}
Vue 3.0의 주요 장점
- 성능 향상: 번들 크기 감소, 렌더링 속도 개선
- 더 나은 TypeScript 지원
- Tree-shaking 지원: 사용하지 않는 기능 제거
- 향상된 코드 재사용성: Composition API를 통한 로직 공유
- 유지보수성 개선: 더 명확한 코드 구조
Vue 3는 Vue 2의 모든 장점을 유지하면서도 현대적인 웹 개발 요구사항을 충족시키는 강력한 프레임워크로 발전했습니다.