Vue.js Reference
Vue.js 프레임워크 레퍼런스
Vue.js Reference 소개
이 Vue.js 레퍼런스는 컴포넌트, Composition API, 디렉티브, 상태관리, 라우터, 라이프사이클의 6개 카테고리로 구성된 Vue 3 개발을 위한 완전한 검색 가능 치트 시트입니다. 각 항목은 TypeScript를 사용한 최신 script setup 방식의 코드 예제와 함께 구문 패턴을 제공하며, Single File Component 구조와 defineProps/defineEmits부터 storeToRefs를 활용한 Pinia 스토어와 Vue Router 내비게이션 가드까지 다룹니다.
Composition API 섹션은 Vue 3의 핵심인 반응형 프리미티브를 문서화합니다: 원시 값을 위한 ref()(.value 접근 필요), 객체를 위한 reactive(), 파생 상태를 위한 computed(), 부수 효과를 위한 watch()와 watchEffect(), 재사용 가능한 상태 로직을 위한 컴포저블(커스텀 훅). 디렉티브 섹션은 v-if/v-else/v-show 조건부 렌더링, :key 바인딩이 있는 v-for 리스트 렌더링, v-bind/v-on 축약형(: 및 @), .number와 .trim 수정자를 가진 v-model, 커스텀 디렉티브를 다룹니다.
상태관리는 Composition API 구문의 defineStore를 사용하는 Pinia(공식 Vue 스토어 라이브러리)와 반응형 디스트럭처링을 위한 storeToRefs, 그리고 깊이 중첩된 컴포넌트 간 의존성 주입을 위한 provide/inject API를 통해 다룹니다. 라우터 섹션은 createRouter 설정, useRoute/useRouter 컴포저블, beforeEach 내비게이션 가드, RouterView/RouterLink 컴포넌트 사용법을 포함합니다.
주요 기능
- script setup lang="ts", template, scoped style 블록으로 구성된 Single File Component(SFC) 구조 설명
- Composition API 프리미티브: ref vs reactive, computed 속성, watch/watchEffect 감시자, 컴포저블 패턴
- TypeScript 기반 props와 emits: 완전한 타입 추론 예제와 함께하는 defineProps<T>()와 defineEmits<T>()
- 완전한 디렉티브 레퍼런스: v-if/v-else-if/v-else, v-show, :key 포함 v-for, v-bind, v-on, 수정자 포함 v-model
- Composition API 스타일(setup 함수로 defineStore)과 반응형 접근을 위한 storeToRefs를 사용하는 Pinia 스토어 정의
- createWebHistory, 동적 라우트 파라미터, useRoute/useRouter, 내비게이션 가드를 포함한 Vue Router 설정
- 라이프사이클 훅 문서화: onMounted, onUpdated, onUnmounted, DOM 업데이트 후 실행을 위한 nextTick
- defineModel<T>()을 사용한 컴포넌트 v-model, template #header 구문의 이름 있는 슬롯, DI를 위한 provide/inject
자주 묻는 질문
Vue 3에서 ref()와 reactive()의 차이는 무엇인가요?
ref()는 값을 반응형 참조 객체로 감싸며 모든 타입(원시값, 객체, 배열)에서 작동합니다. 스크립트에서는 .value로 접근하지만 템플릿에서는 불필요합니다. reactive()는 객체의 깊은 반응형 프록시를 생성하며 .value가 필요 없지만, 객체에서만 작동하고 디스트럭처링하면 반응성을 잃습니다. 기본적으로 ref()를 사용하고, .value 없이 접근하고 싶은 관련 상태 그룹에는 reactive()를 사용하세요.
script setup에서 타입이 지정된 props와 emits를 정의하려면?
defineProps<{ title: string; count?: number }>()로 완전한 TypeScript 추론이 가능한 타입 전용 props 선언을 사용합니다. emits는 defineEmits<{ (e: "update", value: string): void; (e: "delete", id: number): void }>()로 emit 호출과 부모 리스너 모두에서 타입 검사를 받습니다. 두 함수 모두 임포트 불필요한 컴파일러 매크로입니다. withDefaults(defineProps<Props>(), { count: 0 })로 기본값도 설정할 수 있습니다.
watch()와 watchEffect()는 언제 사용해야 하나요?
watch()는 감시할 반응형 소스를 명시적으로 지정하고 콜백에서 이전/새 값을 모두 제공하여 특정 상태 변경 반응이나 비교에 적합합니다. watchEffect()는 콜백 내에서 접근한 모든 반응형 의존성을 자동으로 추적하고 즉시 실행되어 여러 반응형 값에 의존하는 부수 효과에 편리합니다. 세밀한 제어가 필요하면 watch()를, 간단한 반응형 부수 효과에는 watchEffect()를 사용하세요.
Pinia가 Vuex와 다른 점과 권장되는 이유는?
Pinia는 Vuex를 대체하는 공식 Vue 스토어 라이브러리입니다. 주요 개선점: mutations 없음(actions에서 직접 상태 변경), 자동 타입 추론이 가능한 완전한 TypeScript 지원, ref/computed를 사용하는 Composition API 스타일 스토어, 중첩 모듈 없이 설계된 모듈화, devtools 통합. Vue 3 패턴과의 일관성을 위해 Composition API 구문(setup 함수)이 Options API 스타일보다 선호됩니다.
Pinia에서 storeToRefs()의 목적은 무엇인가요?
Pinia 스토어를 직접 디스트럭처링하면 반응형 연결이 끊어져 값이 일반 비반응형 복사본이 됩니다. storeToRefs()는 스토어의 state와 getters를 반응성을 유지하는 개별 ref로 변환하여 디스트럭처링할 수 있습니다: const { count, doubled } = storeToRefs(store). actions(메서드)는 단순 함수이므로 storeToRefs가 아닌 스토어에서 직접 디스트럭처링해야 합니다.
Vue Router 내비게이션 가드는 어떻게 작동하나요?
내비게이션 가드는 라우트 전환을 가로챕니다. 전역 가드 router.beforeEach((to, from) => {...})는 모든 내비게이션 전에 실행됩니다. false를 반환하면 취소, 라우트 객체를 반환하면 리다이렉트, 아무것도 반환하지 않거나 true를 반환하면 진행합니다. 라우트 레벨 가드는 라우트 정의에서 beforeEnter를 사용합니다. 인증 확인, 역할 기반 접근 제어, 데이터 사전 로딩에 주로 사용됩니다.
컴포저블이란 무엇이며 어떻게 만드나요?
컴포저블은 Composition API를 사용하여 재사용 가능한 상태 로직을 캡슐화하는 함수로, React 훅과 유사합니다. "use" 명명 규칙(예: useMouse, useFetch)을 따릅니다. 내부에서 ref(), computed(), onMounted() 등을 사용하여 반응형 상태와 라이프사이클 훅을 생성하고 반응형 값을 반환합니다. 믹스인이나 상속 없이 컴포넌트 간 공유가 가능하며, 단순 함수 호출이므로 깔끔하게 조합됩니다.
Vue 3에서 커스텀 컴포넌트의 v-model은 어떻게 작동하나요?
Vue 3.4+에서는 자식 컴포넌트에서 defineModel<string>()을 사용하여 양방향 바인딩을 만듭니다. 부모는 <CustomInput v-model="name" />으로 사용합니다. 내부적으로 "modelValue"라는 prop과 "update:modelValue"라는 emit에 해당합니다. 이름 있는 인자로 여러 v-model을 가질 수 있습니다: defineModel<number>("count")와 <Component v-model:count="num" /> 조합. 각 v-model은 defineModel의 두 번째 인자로 접근하는 수정자도 가질 수 있습니다.