pageservice.tistory.com

프론트엔드 개발 실무/Vue3 + Vite 실전 가이드

[Vite + Vue3 실전 가이드]③ 컴포넌트 설계와 Props/Emit/v-model 완전 이해

free21 2025. 5. 20. 16:40


Vue 3에서 컴포넌트는 재사용성과 유지보수성을 높이기 위한 핵심 단위입니다. 이번 글에서는 컴포넌트를 효과적으로 설계하는 방법과 props, emit, v-model을 활용한 데이터 흐름 구조를 실무 관점에서 정리합니다.

 

컴포넌트 분리 및 구조화

주제 :
컴포넌트를 어떻게 분리하고 설계해야 하는가?
핵심 개념 :
3단계로 구조화합니다.
핵심 기능 :
역할 중심, 관심사 분리, 중첩 구조 유지
사용 이유 :
각 컴포넌트는 하나의 역할만 담당해야 유지보수가 쉬워집니다.
사용 예시 :

📁 components/
 ├─ BaseButton.vue     (공통 버튼)
 ├─ ProductCard.vue     (상품 카드)
 └─ ProductList.vue     (상품 목록)
  • Base 계열 컴포넌트: 재사용을 위해 스타일과 동작을 캡슐화
  • 도메인 컴포넌트: 특정 페이지/업무에 특화된 역할 수행
  • 페이지 컴포넌트: 여러 도메인 컴포넌트를 조합하여 완성된 화면 구성

Props를 통한 데이터 전달

주제 : 부모 → 자식 데이터 흐름
핵심 개념 : 1개의 방향, 단방향 데이터 전달
핵심 기능 : props를 통해 부모는 자식에 값을 전달합니다.
사용 이유 : 데이터의 흐름을 예측 가능하게 만들고, 컴포넌트 간 결합도를 낮춥니다.
사용 예시 :

<!-- 부모 컴포넌트 -->
<ProductCard :title="product.title" :price="product.price" />

<!-- 자식 컴포넌트 -->
<script setup>
defineProps({
  title: String,
  price: Number
})
</script>
  • defineProps()는 Composition API 방식에서 사용하는 props 선언 방식입니다.
  • 부모가 넘긴 데이터를 자식이 가공 없이 보여주는 것이 이상적입니다.

Emit을 통한 자식 → 부모 이벤트 전달

Theme: 자식 → 부모의 데이터 상향 흐름
Number: emit으로 상향 전달
Point: 자식 컴포넌트는 emit을 통해 부모에게 이벤트를 전달합니다.
Reason: 자식은 부모의 상태를 직접 변경하지 않고, 이벤트만 발생시킵니다.
사용 예시 :

<!-- 자식 컴포넌트 -->
<script setup>
const emit = defineEmits(['delete'])
const onDelete = () => emit('delete', itemId)
</script>

<template>
  <button @click="onDelete">삭제</button>
</template>

<!-- 부모 컴포넌트 -->
<ProductCard @delete="handleDelete" />
  • defineEmits()는 자식이 어떤 이벤트를 발생시킬지 명시합니다.
  • 이벤트명은 kebab-case를 기본으로 하며, 커스텀 이벤트 명명 규칙을 일관되게 유지해야 합니다.

v-model의 양방향 바인딩 구조

주제 : 양방향 바인딩을 컴포넌트에 적용하는 방법
항목: 2개 개념, props + emit
핵심포인트 : modelValue와 update:modelValue 이벤트의 조합
필요이유 : v-model은 내부 상태를 외부와 동기화할 수 있는 수단입니다.
예시설명 :

<!-- 부모 컴포넌트 -->
<MyInput v-model="username" />

<!-- 자식 컴포넌트 -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const onInput = (event) => {
  emit('update:modelValue', event.target.value)
}
</script>

<template>
  <input :value="modelValue" @input="onInput" />
</template>
  • v-model은 내부에서는 modelValue를 prop으로 받고, 변경 시 update:modelValue를 emit합니다.
  • Vue 3에서는 v-model:customProp 형식으로 사용자 정의 바인딩도 가능합니다.

핵심 요점 정리

  • 컴포넌트는 관심사 단위로 분리하고, 재사용성과 유지보수를 고려해 설계합니다.
  • props는 부모 → 자식 데이터 전달, emit은 자식 → 부모 이벤트 전달의 역할을 합니다.
  • v-model은 props와 emit의 합성으로 양방향 바인딩을 실현합니다.
  • 데이터 흐름의 방향성과 책임 분리를 명확히 유지하는 것이 Vue 컴포넌트 아키텍처의 핵심입니다.


💬 댓글

이번 글이 도움이 되었길 바랍니다. 궁금한 점이나 요청이 있다면 언제든 댓글로 남겨주세요. 댓글은 저에게 큰 힘이 됩니다. 다음 글도 기대해주세요.

 

▲ TOP