CompositionAPI 완벽 마스터
CompositionAPI의 핵심 개념과 실전 활용법
학습 항목
이미지 로딩 중...
Vue.js 실전 프로젝트 완벽 가이드
Vue.js 3의 Composition API와 고급 패턴을 활용한 실전 프로젝트 구축 방법을 다룹니다. Pinia 상태관리, Vue Router, 그리고 최신 Vue 3 기능들을 포함합니다.
들어가며
이 글에서는 Vue.js 실전 프로젝트 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- Composition_API_기본_구조
- Pinia_상태관리_Store
- Custom_Composable_함수
- Vue_Router_동적_라우팅
- Provide_Inject_의존성_주입
- Watch_Watcheffect_반응형_추적
- Async_Component_코드_스플리팅
- Teleport_포탈_구현
- Custom_Directive_생성
- Reactive_Form_Validation
- Suspense_비동기_처리
- Composable_API_통합
1. Composition_API_기본_구조
개요
Vue 3의 Composition API는 setup 함수를 통해 컴포넌트 로직을 구성합니다. ref와 reactive를 사용해 반응형 데이터를 관리할 수 있습니다.
코드 예제
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++
}
</script>
설명
script setup을 사용하면 보일러플레이트 코드 없이 간결하게 컴포넌트를 작성할 수 있습니다. ref는 원시값을, reactive는 객체를 반응형으로 만듭니다.
2. Pinia_상태관리_Store
개요
Pinia는 Vue 3의 공식 상태관리 라이브러리입니다. store를 정의하고 여러 컴포넌트에서 공유할 수 있습니다.
코드 예제
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ name: '', age: 0 }),
getters: {
isAdult: (state) => state.age >= 18
},
actions: {
updateUser(name, age) {
this.name = name
this.age = age
}
}
})
설명
defineStore로 store를 정의하고 state, getters, actions를 통해 상태를 관리합니다. 컴포넌트에서 useUserStore()로 접근할 수 있습니다.
3. Custom_Composable_함수
개요
Composable은 재사용 가능한 로직을 캡슐화하는 함수입니다. React Hooks와 유사하게 상태와 로직을 공유할 수 있습니다.
코드 예제
import { ref, onMounted, onUnmounted } from 'vue'
export function useMousePosition() {
const x = ref(0)
const y = ref(0)
const update = (e) => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
설명
Composable 함수는 'use' 접두사를 사용하고, 반응형 데이터와 라이프사이클 훅을 포함할 수 있습니다. 여러 컴포넌트에서 재사용 가능합니다.
4. Vue_Router_동적_라우팅
개요
Vue Router를 사용해 동적 라우팅과 네비게이션 가드를 구현할 수 있습니다. 라우트 파라미터를 통해 데이터를 전달합니다.
코드 예제
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/user/:id',
component: UserProfile,
beforeEnter: (to, from) => {
if (!isAuthenticated()) return '/login'
}
}
]
})
설명
동적 세그먼트(:id)로 파라미터를 받고, beforeEnter 가드로 접근 제어를 합니다. 컴포넌트에서 useRoute()로 파라미터를 접근합니다.
5. Provide_Inject_의존성_주입
개요
Provide/Inject는 props drilling 없이 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 수 있습니다.
코드 예제
// Parent.vue
import { provide, ref } from 'vue'
const theme = ref('dark')
provide('theme', theme)
// Child.vue
import { inject } from 'vue'
const theme = inject('theme')
설명
provide로 데이터를 제공하고 inject로 받습니다. 중간 컴포넌트를 거치지 않고 깊은 계층의 자식에게 데이터를 전달할 수 있습니다.
6. Watch_Watcheffect_반응형_추적
개요
watch는 특정 데이터의 변화를 감지하고, watchEffect는 사용된 모든 반응형 데이터를 자동으로 추적합니다.
코드 예제
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const name = ref('Vue')
watch(count, (newVal, oldVal) => {
console.log(`Count: ${oldVal} -> ${newVal}`)
})
watchEffect(() => {
console.log(`${name.value}: ${count.value}`)
})
설명
watch는 명시적으로 감시할 대상을 지정하고, watchEffect는 함수 내에서 사용된 반응형 데이터를 자동으로 추적합니다.
7. Async_Component_코드_스플리팅
개요
defineAsyncComponent를 사용해 컴포넌트를 비동기로 로드하여 초기 번들 크기를 줄일 수 있습니다.
코드 예제
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent({
loader: () => import('./HeavyComponent.vue'),
loadingComponent: LoadingSpinner,
errorComponent: ErrorDisplay,
delay: 200,
timeout: 3000
})
설명
컴포넌트를 필요할 때만 로드하여 성능을 최적화합니다. 로딩 상태와 에러 처리 컴포넌트를 지정할 수 있습니다.
8. Teleport_포탈_구현
개요
Teleport는 컴포넌트의 렌더링 위치를 DOM의 다른 곳으로 이동시킵니다. 모달이나 토스트 메시지에 유용합니다.
코드 예제
<template>
<button @click="showModal = true">Open Modal</button>
<Teleport to="body">
<div v-if="showModal" class="modal">
<p>Modal Content</p>
<button @click="showModal = false">Close</button>
</div>
</Teleport>
</template>
설명
Teleport의 to 속성으로 렌더링 위치를 지정합니다. CSS 스타일링과 z-index 문제를 해결할 수 있습니다.
9. Custom_Directive_생성
개요
커스텀 디렉티브를 만들어 DOM 조작 로직을 재사용할 수 있습니다. Vue의 라이프사이클과 통합됩니다.
코드 예제
const vFocus = {
mounted: (el) => el.focus(),
updated: (el, binding) => {
if (binding.value) el.focus()
}
}
// 사용
<template>
<input v-focus="shouldFocus" />
</template>
설명
디렉티브 훅(mounted, updated 등)을 사용해 DOM 요소의 생명주기에 맞춰 동작합니다. v- 접두사로 사용합니다.
10. Reactive_Form_Validation
개요
반응형 시스템을 활용한 실시간 폼 검증을 구현합니다. computed와 watch를 조합하여 복잡한 검증 로직을 처리합니다.
코드 예제
import { ref, computed } from 'vue'
const email = ref('')
const password = ref('')
const emailError = computed(() => {
return email.value && !email.value.includes('@')
? 'Invalid email' : ''
})
const isValid = computed(() =>
email.value && password.value.length >= 8 && !emailError.value
)
설명
computed를 사용해 입력값이 변경될 때마다 자동으로 검증이 실행됩니다. 여러 필드의 검증 상태를 조합하여 폼의 전체 유효성을 판단할 수 있습니다.
11. Suspense_비동기_처리
개요
Suspense는 비동기 컴포넌트의 로딩 상태를 선언적으로 처리합니다. 여러 비동기 컴포넌트를 한 번에 관리할 수 있습니다.
코드 예제
<template>
<Suspense>
<template #default>
<AsyncData />
</template>
<template #fallback>
<LoadingSpinner />
</template>
</Suspense>
</template>
설명
default 슬롯에 비동기 컴포넌트를, fallback 슬롯에 로딩 UI를 배치합니다. 여러 비동기 작업이 모두 완료될 때까지 fallback을 보여줍니다.
12. Composable_API_통합
개요
fetch API를 Composable로 래핑하여 재사용 가능한 데이터 fetching 로직을 만듭니다. 로딩, 에러 상태도 함께 관리합니다.
코드 예제
import { ref } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(false)
const fetchData = async () => {
loading.value = true
try {
const res = await fetch(url)
data.value = await res.json()
} catch (e) {
error.value = e
} finally {
loading.value = false
}
}
return { data, error, loading, fetchData }
}
설명
데이터 fetching 로직을 Composable로 캡슐화하여 여러 컴포넌트에서 일관된 방식으로 API를 호출할 수 있습니다. 로딩과 에러 상태를 자동으로 관리합니다. ``` Vue.js 3의 고급 기능들을 활용한 실전 프로젝트 카드 뉴스를 생성했습니다. Composition API, Pinia, Vue Router, 그리고 고급 패턴들을 포함하여 총 12개의 카드로 구성했습니다.
마치며
이번 글에서는 Vue.js 실전 프로젝트 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Vue #CompositionAPI #Pinia #VueRouter #Reactivity