computed : 계산값
watch : 사이드 이펙트
1. computed
- 목적: 데이터를 가공해서 새로운 값을 자동으로 계산하고, 이 계산된 값을 캐시해서 효율적으로 사용하기 위해 쓰임.
- 특징:
- 캐싱이 적용되기 때문에 데이터가 변경되지 않으면 기존의 계산된 값을 재사용함.
- 주로 간단한 계산이나 변형된 데이터를 반영하는 데 적합함.
- 계산된 값을 자동으로 템플릿에 반응형으로 업데이트해줌.
2. watch
목적: 특정 데이터의 변화를 감시하고, 그 변화가 발생했을 때 **부수적인 작업(사이드 이펙트)**을 수행함.
특징:
- 데이터의 변화가 있을 때마다 콜백 함수를 실행해서 필요한 작업을 할 수 있음.
- 주로 API 호출, 애니메이션, 비동기 작업과 같은 데이터 변화에 따른 외부 액션을 처리할 때 사용함.
- 변화에 따라 명시적인 행동을 요구하는 경우 적합함.
예제 비교
1. computed 예제
사용자의 이름과 성을 합쳐서 전체 이름을 반환하는 경우
<template>
<div>
<p>First Name: <input v-model="firstName"></p>
<p>Last Name: <input v-model="lastName"></p>
<p>Full Name: {{ fullName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe',
};
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
};
</script>
- computed 사용 이유: firstName이나 lastName이 변경되면 자동으로 전체 이름(fullName)이 업데이트됨.
- 캐싱의 이점: firstName과 lastName이 변경되지 않으면 fullName은 다시 계산되지 않고 캐시된 값을 사용함.
- 적합한 상황: 단순히 데이터를 가공하거나 연산된 결과를 사용할 때.
2. watch 예제
사용자의 나이(age)가 변경될 때마다 로그를 남기거나 API를 호출하는 경우
<template>
<div>
<p>Age: <input v-model="age" type="number"></p>
</div>
</template>
<script>
export default {
data() {
return {
age: 25,
};
},
watch: {
age(newAge, oldAge) {
console.log(`Age changed from ${oldAge} to ${newAge}`);
// 나이 변경 시 서버에 업데이트 요청
this.updateAgeOnServer(newAge);
}
},
methods: {
updateAgeOnServer(newAge) {
// 비동기 작업으로 서버에 나이 업데이트
console.log(`Updating age to ${newAge} on the server...`);
// 실제 API 호출은 여기에 작성
}
}
};
</script>
- watch 사용 이유: age가 변경될 때마다 부수적인 작업(API 호출, 로그 남기기 등)을 수행해야 함.
- 사이드 이펙트 처리: 데이터의 변화에 따라 직접적인 액션을 수행해야 할 때 적합함.
- 적합한 상황: 특정 데이터가 변할 때 외부 시스템과 연동하거나 비동기 작업과 같은 사이드 이펙트가 필요할 때.
요소의 크기 변화에 따른 애니메이션 적용
특정 데이터(boxSize)가 변경될 때마다 박스의 크기를 부드럽게 변화시키는 애니메이션을 적용
사용자가 버튼을 클릭할 때마다 박스의 크기를 변경하고, GSAP를 사용해 그 변화가 부드럽게 이루어지도록 애니메이션을 적용
<template>
<div>
<button @click="increaseSize">Increase Box Size</button>
<button @click="decreaseSize">Decrease Box Size</button>
<div class="box" ref="box"></div>
</div>
</template>
<script>
import gsap from 'gsap';
export default {
data() {
return {
boxSize: 100, // 박스의 기본 크기 (px)
};
},
watch: {
boxSize(newSize) {
gsap.to(this.$refs.box, {
duration: 1, // 애니메이션 지속 시간
width: `${newSize}px`,
height: `${newSize}px`,
});
}
},
methods: {
increaseSize() {
this.boxSize += 50; // 박스 크기 50px 증가
},
decreaseSize() {
if (this.boxSize > 50) {
this.boxSize -= 50; // 박스 크기 50px 감소
}
}
}
};
</script>
<style scoped>
.box {
width: 100px;
height: 100px;
background-color: lightblue;
margin-top: 20px;
}
</style>
설명
데이터 (boxSize)의 변화 감지:
- boxSize라는 데이터를 사용해서 박스의 크기를 정의
- 사용자가 버튼을 클릭할 때마다 increaseSize() 또는 decreaseSize() 메서드를 호출해서 boxSize 값을 증가시키거나 감소
watch에서 애니메이션 적용:
- watch를 이용해 boxSize가 변경될 때마다 GSAP로 박스의 크기(width와 height)를 부드럽게 애니메이션으로 변경
- 여기서 gsap.to(this.$refs.box, {...})를 사용해서 박스의 크기가 목표 값으로 부드럽게 애니메이션
GSAP를 이용한 애니메이션:
- duration: 1: 애니메이션의 지속 시간을 1초로 설정.
- width와 height: 목표로 하는 박스의 새로운 크기를 설정하고, GSAP가 이를 부드럽게 애니메이션하도록 함.
watch 사용 이유
데이터의 변화 감지:
- boxSize가 변경될 때마다 박스의 크기를 부드럽게 변화시키는 애니메이션을 적용하기 위해 watch가 필요
중간 상태의 부드러운 애니메이션 처리:
- 애니메이션은 중간 상태를 표현하는 작업이기 때문에 단순한 계산 결과를 반환하는 computed보다, 데이터 변화마다 명시적으로 개입할 수 있는 watch가 더 적합
실시간 업데이트:
- 사용자가 버튼을 클릭할 때마다 데이터가 변화하고, 그 변화에 따라 즉각적으로 박스의 크기를 업데이트하면서 애니메이션을 적용해야 하기 때문에, watch가 적절한 선택
왜 computed가 아닌 watch를 사용할까?
- computed는 데이터의 변화를 계산해서 반환하는 데 사용되지만, 여기서는 박스의 크기가 변경될 때마다 애니메이션 효과를 적용하는 것이 목표
- 애니메이션은 데이터 변화에 따른 부드러운 전환을 표현해야 하고, 이 과정에서 지속적인 개입이 필요하기 때문에 computed로 처리하기엔 부족
- 반면 watch는 데이터 변화가 있을 때마다 명시적인 작업을 실행할 수 있어, 애니메이션과 같은 사이드 이펙트를 처리하는 데 적합
요약
- computed는 데이터의 변화를 자동으로 계산하고 그 결과를 캐시해둬서 간단한 데이터 가공에 적합
- watch는 데이터 변화에 따른 사이드 이펙트를 처리하고, 비동기 작업이나 외부 액션을 수행하는 데 적합
- 애니메이션이나 API 호출처럼 데이터 변화에 즉각 반응해야 하는 상황에서는 watch를 사용하는 것이 맞음.
결국 데이터를 가공하는 작업은 computed가 적합하고, 변화에 따른 추가 작업이나 부드러운 전환 처리는 watch가 적절한 선택임
'Vue' 카테고리의 다른 글
vsCode에서 vue, f12 작동 안함 -- jsconfig.js (0) | 2024.11.07 |
---|---|
체크박스 관리 (0) | 2024.11.01 |
v-for와 ref의 동작 (배열) (2) | 2024.10.28 |
선택항목 개수 계산 (0) | 2024.10.28 |
템플릿에서 조건식 vs Computed (0) | 2024.10.28 |