Vue 3 Composition API 활용법



Vue 3의 Composition API를 사용하면 로직을 재사용 가능한 함수로 구성하고 더 유연한 컴포넌트를 작성할 수 있습니다.



Options API vs Composition API


// Options API (Vue 2 스타일)
export default {
data() { return { count: 0 } },
methods: { increment() { this.count++ } },
computed: { double() { return this.count * 2 } }
}

// Composition API (Vue 3)
import { ref, computed } from \047vue\047

export default {
setup() {
const count = ref(0)
const increment = () => count.value++
const double = computed(() => count.value * 2)
return { count, increment, double }
}
}


script setup (권장)


<script setup>
import { ref, computed, onMounted } from \047vue\047

// 반응형 상태
const count = ref(0)
const user = ref({ name: \047홍길동\047 })

// 계산된 속성
const double = computed(() => count.value * 2)

// 메서드
const increment = () => count.value++

// 라이프사이클
onMounted(() => {
console.log(\047컴포넌트 마운트됨\047)
})
</script>

<template>
<button @click="increment">{{ count }}</button>
<p>Double: {{ double }}</p>
</template>


ref vs reactive


import { ref, reactive } from \047vue\047

// ref: 원시값, 개별 값
const count = ref(0)
count.value++ // .value 필요

// reactive: 객체
const state = reactive({
count: 0,
user: { name: \047Kim\047 }
})
state.count++ // .value 불필요

// toRefs: reactive를 ref로 분해
const { count: countRef } = toRefs(state)


Composables (로직 재사용)


// composables/useMouse.js
import { ref, onMounted, onUnmounted } from \047vue\047

export function useMouse() {
const x = ref(0)
const y = ref(0)

const update = (e) => {
x.value = e.pageX
y.value = e.pageY
}

onMounted(() => window.addEventListener(\047mousemove\047, update))
onUnmounted(() => window.removeEventListener(\047mousemove\047, update))

return { x, y }
}

// 컴포넌트에서 사용
<script setup>
import { useMouse } from \047./composables/useMouse\047
const { x, y } = useMouse()
</script>


watch와 watchEffect


import { ref, watch, watchEffect } from \047vue\047

const count = ref(0)
const name = ref(\047\047)

// watch: 명시적 의존성
watch(count, (newVal, oldVal) => {
console.log(\047count changed:\047, newVal)
})

// 여러 소스 감시
watch([count, name], ([newCount, newName]) => {
console.log(newCount, newName)
})

// 깊은 감시
watch(user, (newVal) => {}, { deep: true })

// 즉시 실행
watch(count, handler, { immediate: true })

// watchEffect: 자동 의존성 추적
watchEffect(() => {
console.log(\047count is:\047, count.value)
})


라이프사이클 훅


import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from \047vue\047

onMounted(() => {
console.log(\047DOM 준비됨\047)
})

onUnmounted(() => {
console.log(\047정리 작업\047)
})


Props와 Emits


<script setup>
// Props 정의
const props = defineProps({
title: String,
count: { type: Number, default: 0 }
})

// TypeScript
const props = defineProps<{
title: string
count?: number
}>()

// Emits 정의
const emit = defineEmits([\047update\047, \047delete\047])
emit(\047update\047, newValue)
</script>


provide/inject


// 부모 컴포넌트
import { provide, ref } from \047vue\047
const theme = ref(\047dark\047)
provide(\047theme\047, theme)

// 자식 컴포넌트 (깊이 무관)
import { inject } from \047vue\047
const theme = inject(\047theme\047, \047light\047) // 기본값