Skip to content

Composition API 기본 규칙

10.1.1. 기본 원칙

  • <script setup>을 필수로 사용합니다. Options API는 사용하지 않습니다.
  • TypeScript를 필수로 사용합니다. .vue 파일의 <script> 태그에는 반드시 lang="ts"를 명시합니다.
  • SFC(Single File Component) 내 블록 순서는 <script><template><style> 순서를 따릅니다.
vue
<script setup lang="ts">
import { ref, computed } from 'vue'

const count = ref(0)
const doubled = computed(() => count.value * 2)
</script>

<template>
  <div>
    <p>{{ doubled }}</p>
    <button @click="count++">증가</button>
  </div>
</template>

<style scoped>
/* 스타일 */
</style>

10.1.2. Composable 작성 규칙

  • Composable 함수명은 use 접두사로 시작합니다.
  • 파일 위치는 src/composables/ 디렉토리에 배치합니다.
  • 하나의 파일에 하나의 composable을 정의합니다.
typescript
// src/composables/useUser.ts
import { ref } from 'vue'
import { fetchUser } from '@/api/user'
import type { User } from '@/types/user'

export function useUser(userId: string) {
  const user = ref<User | null>(null)
  const loading = ref(false)
  const error = ref<Error | null>(null)

  async function load() {
    loading.value = true
    try {
      user.value = await fetchUser(userId)
    } catch (e) {
      error.value = e as Error
    } finally {
      loading.value = false
    }
  }

  return { user, loading, error, load }
}

10.1.3. ref와 reactive 사용 규칙

  • 기본 타입(string, number, boolean)에는 ref를 사용합니다.
  • 객체/배열 타입에도 ref를 기본으로 사용합니다. reactive는 깊은 중첩 객체에서 반응성 추적이 필요한 경우에만 제한적으로 사용합니다.
  • ref 값에 접근할 때는 .value를 명시합니다. 템플릿에서는 자동 언래핑됩니다.
typescript
// 올바른 예
const name = ref<string>('')
const items = ref<Item[]>([])
const form = ref<FormData>({ name: '', email: '' })

// 제한적 허용 — reactive 사용
const state = reactive<FormState>({
  fields: { name: '', email: '' },
  errors: {},
  isSubmitting: false,
})

10.1.4. 라이프사이클 훅

  • Composition API 라이프사이클 훅을 사용합니다. Options API 방식의 created, mounted 등은 사용하지 않습니다.
  • <script setup> 내에서 직접 실행되는 코드는 created/beforeCreate에 해당합니다. 별도 훅이 필요하지 않습니다.
Options APIComposition API용도
mountedonMountedDOM 접근, 외부 라이브러리 초기화
unmountedonUnmounted이벤트 리스너 해제, 타이머 정리
updatedonUpdatedDOM 업데이트 후 처리 (사용 최소화)
beforeUnmountonBeforeUnmount정리 작업 시작
typescript
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
})

TIENIPIA QUALIFIED STANDARD