계산된 속성과 감시자 (computed & watch)
어떤 변수의 값이 변할 때, 그에 따라 자동으로 변하는 또 다른 파생된 값을 만들거나, 값이 변할 때마다 특정 동작(API 호출 등)을 실행하게 만들고 싶을 때가 있습니다. 이때 사용하는 핵심 도구가 바로 computed와 watch입니다.
<!-- ==========================================
// 📂 SearchFilter.vue (computed와 watch 실전 예제)
// ========================================== -->
<script setup>
import { ref, computed, watch } from 'vue';
// [1. 상태 선언]
const searchQuery = ref('');
const items = ref(['사과', '바나나', '포도', '딸기', '수박']);
const apiLogs = ref([]);
// ------------------------------------------------
// [💡 computed 사용법] - 원본 데이터를 가공해서 보여줄 때 (캐싱됨)
// ------------------------------------------------
const filteredItems = computed(() => {
// 반드시 return 이 있어야 합니다!
// searchQuery 나 items 의 값이 바뀔 때만 이 함수가 다시 실행됩니다.
return items.value.filter(item => item.includes(searchQuery.value));
});
// ------------------------------------------------
// [💡 watch 사용법] - 데이터가 변할 때 특정 행동을 해야 할 때
// ------------------------------------------------
watch(searchQuery, (newValue, oldValue) => {
// searchQuery 값이 변할 때마다 이 함수가 실행됩니다.
// 이곳에서 백엔드 API를 호출하거나 무거운 작업을 수행하기 좋습니다.
console.log(`검색어가 ${oldValue} 에서 ${newValue} 로 변경됨!`);
apiLogs.value.push(`API 호출: ${newValue} 검색 결과 요청 중...`);
});
</script>
<template>
<div class="p-8 max-w-md mx-auto bg-gray-50 rounded-xl shadow mt-10">
<h2 class="text-2xl font-bold mb-4">과일 검색기</h2>
<!-- 사용자가 검색어를 입력하면 searchQuery의 값이 실시간으로 바뀜 -->
<input
v-model="searchQuery"
placeholder="과일 이름을 입력하세요"
class="w-full border border-blue-300 p-3 rounded-lg mb-6 shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<div class="bg-white p-4 rounded-lg border border-gray-200 mb-6">
<h3 class="font-bold text-gray-700 mb-2">검색 결과 (computed)</h3>
<!-- computed로 가공된 filteredItems 배열을 반복하여 보여줌 -->
<ul class="space-y-1">
<li v-for="fruit in filteredItems" :key="fruit" class="text-blue-600 font-semibold">
🍎 {{ fruit }}
</li>
</ul>
<p v-if="filteredItems.length === 0" class="text-gray-400">결과가 없습니다.</p>
</div>
<div class="bg-black p-4 rounded-lg">
<h3 class="font-bold text-green-400 mb-2">시스템 로그 (watch)</h3>
<ul class="text-xs text-gray-300 font-mono space-y-1 h-20 overflow-y-auto">
<li v-for="(log, idx) in apiLogs" :key="idx">> {{ log }}</li>
</ul>
</div>
</div>
</template>