defineProps() 개념Vue.js 공식 사이트 defineProps()
◼️ defineProps는 Composition API에서 컴포넌트의 props를 정의하는 함수이다.
◼️ setup 함수 내부에서 사용할 수 있으며, <script setup> 문법을 사용할 때 더욱 간결하게 작성할 수 있다.
◼️ 부모 컴포넌트에서 전달된 props를 받을 때 필요하다.
◼️ TypeScript와 함께 사용하면 props의 타입을 명확하게 정의 가능하다.
◼️ Composition API 방식에서는 this가 없기 때문에, defineProps를 사용하여 props를 직접 참조해야 한다.
◼️ defineProps는 setup 내부에서만 사용할 수 있다.
◼️ 컴파일 타임에 처리되며 반환값이 없다. (const props = defineProps() 형태로 사용 가능)
◼️ TypeScript와 함께 사용 가능하다. (defineProps<T>())
◼️ withDefaults를 사용하면 기본값을 설정 가하다.
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>
🠊 부모에서 title과 count를 전달
🠊 자식은 defineProps()를 사용해 props를 받아옴
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': count가 undefined이면 'N/A' 표시
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 필요 없음
💡
propsChildComponent.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 } 구조를 가져야
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()를 함께 사용하여 부모-자식 간 데이터 흐름 관리 가능