# Vue 3 Composition API 완벽 가이드: 리액티비티 마스터하기 > Vue 3 Composition API 실전 가이드입니다. ref, reactive, computed, watch, 컴포저블을 배워 고성능 Vue 애플리케이션을 구축하십시오. - Published: 2026-01-07 - Updated: 2026-04-06 - Author: SharpSkill - Tags: vue 3, composition api, javascript, frontend, reactivity - Reading time: 12 min --- Vue 3의 Composition API는 Vue 컴포넌트 설계 방식에 근본적인 변화를 가져왔습니다. 옵션 단위가 아닌 기능 단위로 코드를 구성할 수 있어 로직 재사용과 복잡한 애플리케이션의 유지보수가 훨씬 수월해집니다. > **사전 지식** > > 이 가이드는 Vue.js의 기본 지식을 전제로 합니다. 각 예제에서는 Vue 3.2에서 도입된 ` ``` 관련 프로퍼티가 여러 개인 객체에는 `reactive`가 더 자연스러운 구문을 제공합니다. `.value`가 필요하지 않습니다. ```javascript // UserProfile.vue ``` 기본 원칙은 다음과 같습니다. 원시 값(문자열, 숫자, 불리언)에는 `ref`를, 구조화된 객체에는 `reactive`를 사용합니다. ## computed를 활용한 계산된 속성 계산된 속성은 리액티브 상태로부터 값을 파생합니다. 캐시가 적용되므로 의존하는 데이터가 변경될 때만 재계산되어 높은 성능을 보장합니다. ```javascript // ProductList.vue ``` 계산된 속성은 getter와 setter를 결합하여 쓰기 가능하게 만들 수도 있습니다. 양방향 변환이 필요한 경우에 유용합니다. ```javascript // FullName.vue ``` ## watch와 watchEffect를 활용한 감시자 감시자는 데이터 변경에 따라 부수 효과를 실행합니다. Vue 3에는 두 가지 방식이 있습니다. 정밀하게 제어할 수 있는 `watch`와 의존성을 자동으로 추적하는 `watchEffect`입니다. > **watch와 watchEffect 중 어떤 것을 사용해야 합니까?** > > `watch`는 의존성을 명시적으로 지정할 수 있으며 변경 전후의 값을 모두 제공합니다. `watchEffect`는 사용하는 모든 리액티브 의존성에 대해 자동으로 실행되므로 더 간결하게 작성할 수 있습니다. ```javascript // SearchComponent.vue ``` 중첩된 객체나 배열을 감시하려면 `watch`에 `deep` 옵션을 지정해야 합니다. ```javascript // DeepWatch.vue ``` ## 재사용 가능한 컴포저블 만들기 컴포저블은 재사용 가능한 리액티브 로직을 캡슐화하는 함수입니다. 컴포넌트 간 코드를 공유하는 데 있어 Composition API의 가장 큰 장점 중 하나입니다. ```javascript // composables/useFetch.js import { ref, watchEffect, toValue } from 'vue' // Composable for HTTP requests // Automatically handles loading, errors, and refetching export function useFetch(url) { const data = ref(null) const error = ref(null) const isLoading = ref(false) // Reusable fetch function async function fetchData() { isLoading.value = true error.value = null try { // toValue() allows accepting a ref or a value const response = await fetch(toValue(url)) if (!response.ok) { throw new Error(`HTTP ${response.status}`) } data.value = await response.json() } catch (e) { error.value = e.message } finally { isLoading.value = false } } // watchEffect for automatic refetch if url is a ref watchEffect(() => { fetchData() }) // Expose state and methods return { data, error, isLoading, refetch: fetchData } } ``` 이 컴포저블을 사용하면 어떤 컴포넌트에서든 선언적으로 데이터를 가져올 수 있습니다. ```javascript // UserList.vue ``` 다음은 유효성 검사를 포함한 폼 상태 관리 컴포저블의 예제입니다. ```javascript // composables/useForm.js import { reactive, computed } from 'vue' // Form management composable export function useForm(initialValues, validationRules) { // Form state const form = reactive({ values: { ...initialValues }, errors: {}, touched: {} }) // Validate a specific field const validateField = (field) => { const rules = validationRules[field] if (!rules) return true for (const rule of rules) { const result = rule(form.values[field]) if (result !== true) { form.errors[field] = result return false } } form.errors[field] = null return true } // Validate entire form const validate = () => { let isValid = true for (const field in validationRules) { if (!validateField(field)) { isValid = false } } return isValid } // computed: form is valid if no errors const isValid = computed(() => { return Object.values(form.errors).every(e => !e) }) // Mark a field as touched (to display errors) const touch = (field) => { form.touched[field] = true validateField(field) } // Reset the form const reset = () => { form.values = { ...initialValues } form.errors = {} form.touched = {} } return { form, isValid, validate, validateField, touch, reset } } ``` ## 라이프사이클 훅 관리 Composition API에서는 라이프사이클 훅을 setup 내에서 호출하는 함수로 제공합니다. 컴포넌트 라이프사이클의 특정 시점에 코드를 실행할 수 있습니다. > **클린업의 중요성** > > 메모리 누수를 방지하기 위해 `onUnmounted`에서 타이머, 이벤트 리스너, 구독 등의 부수 효과를 반드시 정리하십시오. ```javascript // LifecycleDemo.vue ``` ## 템플릿 참조와 DOM 접근 템플릿 참조를 사용하면 DOM 요소나 자식 컴포넌트 인스턴스에 직접 접근할 수 있습니다. 직접 조작이 필요한 경우에 여전히 유용합니다. ```javascript // InputFocus.vue ``` ## Props와 Emits를 활용한 부모-자식 통신 Composition API에서는 `defineProps`와 `defineEmits`를 사용하여 props와 이벤트 선언 방식을 현대화했습니다. TypeScript와의 통합도 우수합니다. ```javascript // ChildComponent.vue ``` ```javascript // ParentComponent.vue ``` ## provide와 inject를 활용한 의존성 주입 props 전달 체인(prop drilling) 없이 멀리 떨어진 컴포넌트 간에 데이터를 공유하기 위해 Vue 3는 `provide`와 `inject`를 제공합니다. ```javascript // App.vue (or an ancestor component) ``` ```javascript // DeepNestedComponent.vue (anywhere in the tree) ``` ## 결론 Vue 3의 Composition API는 Vue 애플리케이션의 코드를 구성하는 강력하고 유연한 방법을 제공합니다. 핵심 요점은 다음과 같습니다. - 원시 값에는 **ref**, 복잡한 객체에는 **reactive**를 사용합니다 - **computed**로 자동 캐싱이 적용되는 파생 값을 정의합니다 - **watch**와 **watchEffect**로 리액티브 부수 효과를 관리합니다 - **컴포저블**로 컴포넌트 간 로직을 추출하고 재사용합니다 - **함수형 라이프사이클 훅**(`onMounted`, `onUnmounted` 등)을 활용합니다 - **provide/inject**로 props 전달 체인 없이 의존성 주입을 수행합니다 이 접근 방식을 통해 유지보수성과 테스트 용이성이 뛰어난 애플리케이션을 구축하면서 TypeScript와의 우수한 통합도 실현할 수 있습니다. 다음 단계로 비동기 컴포저블이나 Pinia를 활용한 전역 상태 관리와 같은 고급 패턴을 탐구해 보십시오. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/ko/blog/vue-nuxt/vue-3-composition-api-complete-guide