minstudio

계산된 속성과 감시자 (computed & watch)

어떤 변수의 값이 변할 때, 그에 따라 자동으로 변하는 또 다른 파생된 값을 만들거나, 값이 변할 때마다 특정 동작(API 호출 등)을 실행하게 만들고 싶을 때가 있습니다. 이때 사용하는 핵심 도구가 바로 computedwatch입니다.

🧠 computed vs watch 완벽 가이드 computed (계산된 속성) 원본 데이터 (ref) 가공된 새로운 데이터 ✅ 값을 반환(return) 해야 함 ✅ 결과를 캐싱(저장)하여 성능 우수 watch (감시자) 감시할 데이터 (ref) 값이 변하면? 특정 동작 (Side Effect) ✅ 값을 반환할 필요 없음 ✅ API 호출, DOM 조작에 적합
<!-- ==========================================
// 📂 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>
계산된 속성과 감시자 (computed & watch) | Minstudio