--- id: wiki-2026-0508-composition-api title: Composition API (Vue 3) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Vue Composition API, setup script] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [vue, composition-api, reactivity, frontend] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Vue 3 --- # Composition API (Vue 3) ## 매 한 줄 > **"매 reactive primitive 으로 logic 을 조합한다"**. Composition API 는 Vue 3 의 `setup()` / ` ``` ### Typed props + emits + v-model ```vue ``` ### reactive with toRefs (avoid losing reactivity) ```ts import { reactive, toRefs } from 'vue'; export function useUser() { const state = reactive({ name: 'Ada', age: 36 }); return { ...toRefs(state) }; // 매 destructurable + reactive } ``` ### watch with explicit source ```ts import { ref, watch } from 'vue'; const query = ref(''); watch(query, async (q, _old, onCleanup) => { const ctrl = new AbortController(); onCleanup(() => ctrl.abort()); const r = await fetch(`/search?q=${q}`, { signal: ctrl.signal }); // ... }); ``` ### watchEffect (auto-track) ```ts import { ref, watchEffect } from 'vue'; const userId = ref(1); watchEffect(async () => { const r = await fetch(`/api/users/${userId.value}`); user.value = await r.json(); }); ``` ### Provide / inject (typed) ```ts // keys.ts import type { InjectionKey, Ref } from 'vue'; export const ThemeKey: InjectionKey> = Symbol('theme'); // Parent import { provide, ref } from 'vue'; const theme = ref<'light' | 'dark'>('dark'); provide(ThemeKey, theme); // Child import { inject } from 'vue'; const theme = inject(ThemeKey)!; ``` ### Async setup with Suspense ```vue ``` ### Lifecycle hooks ```ts import { onMounted, onUnmounted } from 'vue'; onMounted(() => console.log('mounted')); onUnmounted(() => console.log('cleanup')); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | New Vue 3 project | Composition + `