Vue3 defineProps() 이란?

웰치스·2025년 3월 15일

Vue.js

목록 보기
2/4
post-thumbnail

🎯 defineProps() 개념


1️⃣ 기본 개념

Vue.js 공식 사이트 defineProps()
◼️ definePropsComposition API에서 컴포넌트의 props를 정의하는 함수이다.
◼️ setup 함수 내부에서 사용할 수 있으며, <script setup> 문법을 사용할 때 더욱 간결하게 작성할 수 있다.


2️⃣ 사용 목적

◼️ 부모 컴포넌트에서 전달된 props를 받을 때 필요하다.
◼️ TypeScript와 함께 사용하면 props의 타입을 명확하게 정의 가능하다.
◼️ Composition API 방식에서는 this가 없기 때문에, defineProps를 사용하여 props를 직접 참조해야 한다.


3️⃣ 특징

◼️ definePropssetup 내부에서만 사용할 수 있다.
◼️ 컴파일 타임에 처리되며 반환값이 없다. (const props = defineProps() 형태로 사용 가능)
◼️ TypeScript와 함께 사용 가능하다. (defineProps<T>())
◼️ withDefaults를 사용하면 기본값을 설정 가하다.


4️⃣ 예제

ChildComponent.vue (자식 컴포넌트)

<script setup>
defineProps({
  title: String,
  count: Number,
});
</script>

<template>
  <h1>{{ title }}</h1>
  <p>Count: {{ count }}</p>
</template>

ParentComponent.vue (부모 컴포넌트)

<template>
  <ChildComponent title="Hello Vue 3!" :count="10" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

🠊 부모에서 titlecount를 전달
🠊 자식은 defineProps()를 사용해 props를 받아옴


5️⃣ TypeScript와 함께 사용하기

defineProps<T>()를 사용하면 타입 안정성을 보장할 수 있다.
ChildComponent.vue (TypeScript 사용)

<script setup lang="ts">
defineProps<{
  title: string;
  count?: number; // 선택적 prop
}>();
</script>

<template>
  <h1>{{ title }}</h1>
  <p>Count: {{ count ?? 'N/A' }}</p>
</template>

◼️ title: 반드시 문자열이어야 함
◼️ count: 선택적 prop (undefined 가능)
◼️ count ?? 'N/A': countundefined이면 'N/A' 표시


6️⃣ withDefaults 로 기본값 설정

<script setup lang="ts">
const props = withDefaults(defineProps<{
  title: string;
  count?: number;
}>(), {
  count: 0,
});
</script>

<template>
  <h1>{{ title }}</h1>
  <p>Count: {{ count }}</p>
</template>

💡 Tip
withDefaults 사용 시 바로 props 사용 가능

<script setup lang="ts">
const props = withDefaults(defineProps<{ targetCode?: string }>(), {
  targetCode: '',
});

console.log(props.targetCode); // 바로 사용 가능!
</script>

props.targetCode는 이미 반응형이므로 ref로 감쌀 필요 없음!

🚀 그런데 ref를 써야 할 때는?

1️⃣ props 값을 변경해야 할 경우 → ref 사용
◼️props는 읽기 전용(reactive but readonly) 이므로, 직접 수정할 수 없다.
◼️ 만약 props.targetCode를 변경하려면 ref를 사용해야 한다.

<script setup lang="ts">
const props = withDefaults(defineProps<{ targetCode?: string }>(), {
  targetCode: '',
});

const targetCode = ref(props.targetCode); // ref로 변경 가능한 상태로 만들기

const updateCode = () => {
  targetCode.value = '새로운 코드';
};
</script>

<template>
  <p>{{ targetCode }}</p>
  <button @click="updateCode">변경</button>
</template>

ref(props.targetCode)로 감싸면 이제 변경 가능
targetCode.value = '새로운 코드'처럼 업데이트할 수 있음

2️⃣ props 값을 그대로 사용할 경우 → ref 필요 없음

<script setup lang="ts">
const props = withDefaults(defineProps<{ targetCode?: string }>(), {
  targetCode: '',
});
</script>

<template>
  <p>{{ props.targetCode }}</p> <!-- 그냥 사용 가능 -->
</template>

✔ 읽기 전용으로 그냥 사용할 때는 ref 필요 없음
💡


7️⃣ 객체 타입의 props

ChildComponent.vue

<script setup lang="ts">
defineProps<{
  user: {
    name: string;
    age: number;
  };
}>();
</script>

<template>
  <p>Name: {{ user.name }}</p>
  <p>Age: {{ user.age }}</p>
</template>

ParentComponent.vue

<template>
  <ChildComponent :user="{ name: 'Alice', age: 25 }" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

user{ name: string; age: number } 구조를 가져야


8️⃣ defineProps() + defineEmits() 함께 사용하기

이벤트(emit)를 함께 사용하는 경우 다음과 같이 정의한다.
ChildComponent.vue

<script setup>
const props = defineProps<{
  message: string;
}>();

const emit = defineEmits<{
  (event: 'update', value: string): void;
}>();

const updateMessage = () => {
  emit('update', props.message + '!');
};
</script>

<template>
  <p>{{ message }}</p>
  <button @click="updateMessage">Update</button>
</template>

ParentComponent.vue

<template>
  <ChildComponent :message="msg" @update="handleUpdate" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const msg = ref('Hello');

const handleUpdate = (newMessage: string) => {
  msg.value = newMessage;
};
</script>

@update="handleUpdate"를 통해 자식에서 전달한 이벤트를 처리
msg의 값이 변경됨


🔥 결론
defineProps()setup 내부에서 props를 정의하는 함수
TypeScript를 사용하면 타입 안정성 증가
withDefaults()로 기본값 설정 가능
defineProps()defineEmits()를 함께 사용하여 부모-자식 간 데이터 흐름 관리 가능

0개의 댓글