728x90
안녕하세요, 개발자 여러분! 이번에는 Vue.js의 Composition API를 사용해 CRUD(Create, Read, Update, Delete) UI를 구성하면서 watch와 computed를 실무적으로 활용하는 방법을 블로그 글 형식으로 풀어보겠습니다. Composition API는 기존 Options API보다 유연하고 모듈화된 코드를 작성할 수 있게 해주며, 특히 로직 재사용성이 뛰어납니다.
1. CRUD UI의 기본 설정
CRUD UI를 구성한다고 가정하면, 사용자 목록을 표시하고 검색, 추가, 수정, 삭제 기능을 제공하는 인터페이스를 구현할 수 있습니다. Composition API를 사용하면 데이터와 로직을 함수 단위로 깔끔하게 분리할 수 있습니다. 먼저 기본 구조를 보겠습니다.
2. computed로 데이터 필터링 구현
computed는 반응형 데이터를 기반으로 계산된 값을 제공하며, 캐싱을 통해 성능을 최적화합니다. 사용자 목록을 검색어로 필터링하는 예제를 Composition API로 작성해보겠습니다.
<template>
<div>
<input v-model="searchQuery" placeholder="사용자 검색" />
<table>
<thead>
<tr>
<th>ID</th>
<th>이름</th>
<th>이메일</th>
</tr>
</thead>
<tbody>
<tr v-for="user in filteredUsers" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
setup() {
const searchQuery = ref('');
const users = ref([
{ id: 1, name: '김철수', email: 'cheolsu@example.com' },
{ id: 2, name: '이영희', email: 'younghee@example.com' },
{ id: 3, name: '박민수', email: 'minsu@example.com' },
]);
const filteredUsers = computed(() => {
return users.value.filter(user =>
user.name.includes(searchQuery.value) || user.email.includes(searchQuery.value)
);
});
return {
searchQuery,
filteredUsers,
};
},
};
</script>
설명: ref로 반응형 데이터를 정의하고, computed로 filteredUsers를 계산합니다. searchQuery가 변경될 때마다 자동으로 필터링된 결과가 UI에 반영됩니다. Composition API에서는 this 없이 변수와 함수를 직접 다루므로 코드가 직관적입니다.
3. watch로 사용자 입력 감지 및 유효성 검사
watch는 특정 데이터의 변화를 감지해 로직을 실행합니다. 사용자 추가 폼에서 입력값의 유효성을 실시간으로 체크하는 예제를 보겠습니다.
<template>
<div>
<h2>사용자 추가</h2>
<input v-model="newUser.name" placeholder="이름" />
<input v-model="newUser.email" placeholder="이메일" />
<button @click="addUser" :disabled="!isFormValid">추가</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
const newUser = reactive({
name: '',
email: '',
});
const isFormValid = ref(false);
const validateForm = () => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
isFormValid.value =
newUser.name.trim().length > 0 && emailRegex.test(newUser.email);
};
watch(
() => [newUser.name, newUser.email],
() => {
validateForm();
},
{ immediate: true }
);
const addUser = () => {
if (isFormValid.value) {
console.log('사용자 추가:', { ...newUser });
newUser.name = '';
newUser.email = '';
}
};
return {
newUser,
isFormValid,
addUser,
};
},
};
</script>
설명: reactive로 객체를 반응형으로 만들고, watch로 newUser의 name과 email 변화를 감지합니다. 배열 형태로 여러 값을 한 번에 감시할 수 있는 점이 Composition API의 강력한 기능 중 하나입니다. 입력값이 변경될 때마다 validateForm이 호출되어 isFormValid를 업데이트합니다.
4. watch와 computed 조합으로 수정 폼 구현
실무에서는 watch와 computed를 함께 사용해 복잡한 상태를 관리하는 경우가 많습니다. 선택된 사용자를 수정하는 폼을 예로 들어보겠습니다.
<template>
<div>
<h2>사용자 수정</h2>
<select v-model="selectedUserId">
<option v-for="user in users" :value="user.id" :key="user.id">
{{ user.name }}
</option>
</select>
<div v-if="selectedUser">
<input v-model="selectedUser.name" />
<input v-model="selectedUser.email" />
<button @click="saveChanges" :disabled="!hasChanges">저장</button>
</div>
</div>
</template>
<script>
import { ref, computed, watch } from 'vue';
export default {
setup() {
const selectedUserId = ref(null);
const users = ref([
{ id: 1, name: '김철수', email: 'cheolsu@example.com' },
{ id: 2, name: '이영희', email: 'younghee@example.com' },
]);
const originalUser = ref(null);
const selectedUser = computed(() => {
return users.value.find(user => user.id === selectedUserId.value);
});
const hasChanges = computed(() => {
if (!selectedUser.value || !originalUser.value) return false;
return (
selectedUser.value.name !== originalUser.value.name ||
selectedUser.value.email !== originalUser.value.email
);
});
watch(selectedUserId, (newId) => {
const user = users.value.find(u => u.id === newId);
originalUser.value = user ? { ...user } : null;
});
const saveChanges = () => {
if (hasChanges.value) {
console.log('변경된 데이터 저장:', selectedUser.value);
originalUser.value = { ...selectedUser.value }; // 원본 동기화
}
};
return {
selectedUserId,
users,
selectedUser,
hasChanges,
saveChanges,
};
},
};
</script>
설명: computed로 selectedUser와 hasChanges를 정의해 선택된 사용자와 변경 여부를 계산합니다. watch는 selectedUserId가 변경될 때 원본 데이터를 originalUser에 저장합니다. 이 조합은 수정 폼에서 데이터 비교와 저장 로직을 깔끔하게 처리합니다.
5. 실무 팁
-
재사용성: Composition API를 활용하면 로직을 별도 함수로 분리해 여러 컴포넌트에서 재사용할 수 있습니다.
-
디바운싱: watch에 debounce를 적용하려면 watch(() => value.value, debounce(handler, 300))처럼 커스텀 로직을 추가하세요.
-
상태 관리: 대규모 앱에서는 Pinia와 함께 사용해 watch와 computed의 부담을 줄이는 것도 추천합니다.
마무리
Composition API를 사용하면 watch와 computed를 더 유연하고 모듈화된 방식으로 활용할 수 있습니다. computed로 데이터를 가공하고, watch로 상태 변화를 감지해 CRUD UI를 효율적으로 구현해보세요. 코드가 깔끔해지고 유지보수도 쉬워질 거예요! 궁금한 점이 있다면 언제든 질문 주세요. Happy coding!
728x90
'Vue.js 를 배워보자' 카테고리의 다른 글
Vue Composition API로 배열 데이터에 segNo 추가하기 (0) | 2025.04.10 |
---|---|
TypeScript에서 & 연산자의 의미와 활용: DeliveryData 예제를 중심으로 (0) | 2025.03.29 |
Vue 컴포넌트와 TypeScript를 활용한 배송 정보 관리: 실무 예제 (0) | 2025.03.29 |
Vue에서 반응형 Lookup 객체로 라디오그룹, 콤보박스, 체크박스 관리하기 (0) | 2025.03.27 |
Vue.js에서 사용되는 모든 특수문자 완벽 정리 (0) | 2025.03.25 |