본문 바로가기
IT프리랜서

Vue.js Composition API 방식으로 html과 혼합하여 간단히 적용하기

by 굿대디~ 2026. 4. 9.
반응형

Vue.js의 Composition API는 Vue 3에서 가장 핵심적이고 근본적인 변화 중 하나입니다. 이전 방식인 Options API가 가진 구조적인 한계를 극복하고, 대규모 애플리케이션 개발의 생산성과 가독성을 혁신적으로 개선한 패턴이라고 이해하시면 됩니다.

아래에서 Composition API가 무엇인지, 왜 필요한지, 그리고 핵심 구성 요소들을 매우 상세하게 설명드리겠습니다.


🚀 1. Composition API란 무엇인가? (개념 정의)

Composition API는 Vue 컴포넌트 내에서 관련된 로직(State, Logic, Side Effect)들을 시간적 순서에 관계없이, 기능별(Feature-based)로 그룹화하여 작성하는 방식을 의미합니다.

🔍 Options API와의 근본적인 차이점

특징 Options API (기존 방식) Composition API (새로운 방식)
로직 분리 방식 관심사별(Concern-based)로 분리 (data, methods, computed, watch 등) 기능별(Feature-based)로 그룹화
문제점 로직이 길어지면, 하나의 기능을 구현하는 코드가 methodscomputed 등 여러 섹션에 분산되어 코드를 따라가기 어렵다 (분산성 문제). 관련 로직을 하나의 묶음으로 응집시켜서 관리하기 매우 쉽다.
핵심 도구 키워드 기반 (Options: data: {}, methods: {})  
함수 기반 (Hooks: setup(), ref(), computed())    
적합한 상황 작고 단순한 컴포넌트. 크고 복잡하며 비즈니스 로직이 복잡한 대규모 컴포넌트.

핵심 요약: Options API가 "데이터 관리는 data에, 함수 처리는 methods에"와 같이 "어디에 넣을지"를 구조적으로 강제했다면, Composition API는 "이 기능에 필요한 모든 로직을 한곳에 모아 놓자"에 초점을 맞춘 접근 방식입니다.


🧱 2. Composition API의 핵심 구조와 도구

Composition API를 사용한다는 것은, 컴포넌트의 라이프사이클(setup() 함수) 내부에서 Vue에서 제공하는 특정 함수(Hooks)들을 호출하여 상태(State)와 반응성(Reactivity)을 관리한다는 의미입니다
.

🥇 2-1. setup() 함수 (진입점)

Vue 3 컴포넌트는 export default 구조 대신 함수 컴포넌트 구조를 사용하며, 모든 반응성 로직은 이 setup() 함수 내에서 시작됩니다.

  • 역할: 컴포넌트가 마운트되기 직전에 실행되는 초기화 지점입니다. 모든 ref, reactive 등의 코드가 여기에 위치합니다.
  • 특징: 컴포넌트의 <script setup> 문법을 사용하면 이 setup()을 명시적으로 작성하지 않아도 됩니다.

🥈 2-2. 반응성(Reactivity) 시스템 (가장 중요!)

Composition API의 근간은 Vue의 반응성 시스템입니다. 자바스크립트의 일반 변수(let count = 0)를 쓰면 값이 변해도 화면이 자동으로 업데이트되지 않습니다. 우리는 변화에 반응하는 변수를 사용해야 합니다
.

ref(): 기본형(Primitive) 데이터를 위한 반응성 객체

  • 사용처: 숫자, 문자열, 불리언 등 원시 타입(Primitive Type)을 감쌀 때 사용합니다.
  • 작동 원리: ref로 감싼 변수를 반드시 .value를 통해 접근하고 변경해야 합니다.
  • 예시:
    import { ref } from 'vue';
    const count = ref(0); // count는 단순 변수가 아니라 ref 객체입니다.
    // 화면에서 사용하거나 변경할 때는 count.value를 써야 합니다.

reactive(): 객체(Object) 데이터를 위한 반응성 객체

  • 사용처: 여러 속성을 가진 객체(Object) 자체를 감쌀 때 사용합니다.
  • 작동 원리: 객체 전체를 감싸기 때문에, 속성 접근 시에는 일반적인 JavaScript 객체처럼 state.name 방식으로 접근할 수 있습니다.
  • 예시:
    import { reactive } from 'vue';
    const state = reactive({
      name: 'VueUser',
      age: 30
    });
    // 접근 및 변경: state.name = 'NewName'

💡 ref vs reactive 선택 가이드:

  • 가장 안전하고 권장되는 패턴: 원시 타입은 ref, 객체 타입은 reactive를 사용하되, 로직의 통일성을 위해 필요한 경우 모든 것을 ref로 감쌀 수도 있습니다.
  • 실습 팁: 초보자라면 원시 타입을 다룰 때나 명확한 구조가 필요할 때 ref() 사용을 습관화하는 것이 좋습니다.

🥉 2-3. computed(): 파생 상태(Derived State)

  • 역할: 다른 반응형 상태(refreactive)를 기반으로 계산되지만, 스스로 변경되지 않는 상태를 만들 때 사용합니다.
  • 특징: 이 값을 가져올 때만 계산하고, 값이 변경되었을 때만 재계산됩니다. (캐싱 효과)
  • 예시: 사용자 이름과 성을 조합하여 '전체 이름'을 계산할 때.
    import { computed } from 'vue';
    const firstName = ref('John');
    const lastName = ref('Doe');
    const fullName = computed(() => `${firstName.value} 
    ${lastName.value}`);
    // firstName이 바뀌면, fullName도 자동으로 업데이트됩니다.

🏅 2-4. watch / watchEffect: 부수 효과(Side Effect) 처리

  • 역할: 특정 반응성 상태(State)가 변경되었을 때 "어떤 동작"을 수행해야 할 때 사용합니다. (예: 로컬스토리지 저장, API 호출, 메시지 띄우기 등)
  • watch(source, callback): 특정 변수나 Getter를 지정하고, 그것이 변경될 때마다 콜백 함수를 실행합니다.
  • watchEffect(callback): 콜백 함수 내부에서 사용된 모든 반응형 상태를 감지하여, 초기 실행 후 상태가 변경될 때마다 자동으로 콜백을 재실행합니다. (설정할 변수가 복잡하지 않을 때 유용)
  • 예시: count가 10이 될 때마다 API 호출을 수행.

✨ 2-5. onMounted 등 라이프사이클 훅 (Hooks)

Composition API는 Options API의 라이프사이클 훅을 함수 형태로 사용합니다.

  • onMounted(() => { ... }): 컴포넌트가 DOM에 성공적으로 마운트된 후에 실행할 로직을 넣습니다. (예: API 호출)
  • onUpdated(() => { ... }): 컴포넌트의 반응형 데이터가 변경되어 DOM이 업데이트된 후에 실행합니다.
  • onUnmounted(() => { ... }): 컴포넌트가 파괴되기 직전에 실행하며, 구독 해지(Cleanup) 로직을 넣을 때 필수적입니다.

🧩 3. 가장 강력한 이점: Custom Composables (커스텀 훅)

Composition API를 배운 이유 중 90%는 바로 이 Custom Composables를 만들기 위해서입니다.

커스텀 훅이란, 특정 기능을 재사용할 수 있도록 setup() 함수와 ref, reactive 같은 훅들을 묶어 별도의 파일(.js 또는 .ts)로 추출한 함수를 말합니다. (React의 Custom Hook과 개념적으로 동일합니다.)

🛠️ 사용 예시: useFetch.js

만약 데이터 가져오기, 로딩 상태 관리, 에러 처리 로직이 3개의 다른 컴포넌트에서 반복된다고 가정해 봅시다.

Options API였다면: 각 컴포넌트의 <script> 블록에 isLoading, data, fetchData 로직을 각자 구현하고, 중복 코드가 발생했을 겁니다.

Composition API를 사용한다면:

  1. useFetch.js 파일에 데이터 패칭 로직 전체를 정의합니다.
  2. 컴포넌트에서 이 훅을 불러옵니다.
  3. // MyComponent.vue <script setup> import { useFetch } from '@/composables/useFetch'; // 데이터와 로직이 깔끔하게 분리되고, 컴포넌트는 그 결과를 사용만 하면 됩니다. const { data, isLoading, error } = useFetch('/api/user/' + userId); </script>

결과:

  • 재사용성: 비즈니스 로직(State, Logic)을 100% 분리하여 여러 컴포넌트에서 재사용할 수 있습니다.
  • 가독성: 컴포넌트의 로직이 "무엇을 하는지" (What)에 초점을 맞추고, "어떻게 구현되었는지" (How)는 훅 내부로 숨기게 되어 코드가 매우 깔끔해집니다.

📝 요약 정리 (최종 점검)

개념 목적 핵심 코드 대체 역할 (Options API)
Composition API 관련 로직을 기능별로 그룹화. setup() 내부의 함수 호출 Options 블록 전체
ref() 원시형 상태를 반응형으로 만듦. const count = ref(0) data() 속성
reactive() 객체 상태를 반응형으로 만듦. const state = reactive({}) data() 속성
computed() 상태를 기반으로 파생되는 값을 계산. const fullName = computed(...) computed 속성
watch() 상태 변경에 따른 부수 효과 처리. watch(source, callback) watch 속성
onMounted() 컴포넌트 마운트 시점의 초기화. onMounted(() => { ... }) mounted()
Composables 복잡한 로직을 외부 파일로 분리하여 재사용. useSomething.js 없음 (이것이 가장 큰 이점)
반응형