[Vue.js] Watch, WatchEffect

ν† λΌλŠ” 개발개발·2023λ…„ 8μ›” 15일
2

Vue.js

λͺ©λ‘ 보기
9/19
post-thumbnail

πŸ“Œ 1. Watch

composition API의 watchλŠ” λ°˜μ‘ν˜• μƒνƒœκ°€ λ³€κ²½ 될 λ•Œλ§ˆλ‹€, 이λ₯Ό κ°μ§€ν•˜μ—¬ νŠΉμ • μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ²Œ ν•˜λŠ” "κ°μ‹œμž μ—­ν• "을 ν•œλ‹€.

watch(/* Source Type */, (newValue, oldValue) => {});

ν•œ λ§ˆλ””λ‘œ, λ°˜μ‘ν˜• μƒνƒœκ°€ λ³€κ²½ λ˜μ—ˆμ„ λ•Œ 이λ₯Ό κ°μ§€ν•˜μ—¬ λ‹€λ₯Έ μž‘μ—…(DOMλ³€κ²½, 비동기 μž‘μ—… λ“±λ“±..)을 ν•΄μ•Όν•˜λŠ” μƒν™©μ—μ„œ μ‚¬μš©ν•˜λŠ” 속성이닀.

κ°„λ‹¨ν•œ μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ³΄μž.

✨ 예제 1
<script setup>
const message = ref('Hello');

watch(message, (newValue, oldValue) => {
	console.log('newValue' : newValue);
  	console.log('oldValue' : oldValue);
})
</script>

μœ„μ˜ μ˜ˆμ‹œμ—μ„œ message의 값이 'Hello World!'둜 λ³€κ²½λœλ‹€λ©΄, μ½˜μ†”μ°½μ—λŠ” λ‹€μŒκ³Ό 같이 좜λ ₯될 것이닀.

newValue : Hello World!
oldValue : Hello



watch의 첫 번째 λ§€κ°œλ³€μˆ˜λŠ” λ‹€μ–‘ν•œ νƒ€μž…(ref, reactive, computed, arrayλ“±)이 될 수 μžˆλ‹€.

✨ 예제 2
const x = ref(0);
const y = ref(0);

// ref
watch(x, (newX) => {
  console.log(newX);
})

// getter
watch(
  () => x.value + y.value,
  (sum) => {
    console.log(sum);
  }
)

// array
watch([x, () => y.value], ([newX, newY]) => {
  console.log(newX, newY);
})



μ—¬κΈ°μ„œ μ£Όμ˜ν•  점은 μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œλŠ” λ°˜μ‘ν˜• 객체의 속성을 λ³Ό 수 μ—†λ‹€λŠ” 것이닀.

μš°λ¦¬λŠ” λ„ˆλ¬΄λ‚˜ λ‹Ήμ—°ν•˜κ²Œλ„ watchλ₯Ό 객체의 속성에도 μ‚¬μš©ν•˜λ €κ³  μ‹œλ„ν•΄λ³Ό 것이닀. (λ‚˜λ„ κ·Έλž¬μœΌλ―€λ‘œ...)

✨ 예제 3
const obj = reactive({ count: 0 });

watch(obj.count, (newValue) => {
	console.log('newValue: ', newValue);
});

watchκ°€ μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠλŠ”λ‹€.
μ™œ 그럴까?

console.log(typeof obj.count);
// number 좜λ ₯

obj.count의 νƒ€μž…μ€ λ°˜μ‘ν˜• 객체가 μ•„λ‹Œ 'number'νƒ€μž…μ΄λ‹€.
κ·ΈλŸ¬λ―€λ‘œ watchκ°€ λ™μž‘ν•˜μ—¬ 감지할 수 μ—†λ‹€.

그러면 방법이 μ—†μ„κΉŒ?
λŒ€μ‹  getterν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.

const obj = reactive({ count: 0 });
watch(() => obj.count, (newValue) => {
  console.log('newValue: ', newValue);
});



또, μ—¬κΈ°μ„œ 객체의 속성이 μ•„λ‹Œ 객체 κ·Έ 자체λ₯Ό 첫번째 λ§€κ°œλ³€μˆ˜λ‘œ μ£Όλ©΄ μ–΄λ–»κ²Œ 될까?

✨ 예제 4
<script setup>
const obj = reactive({ count: 0 });

watch(obj, (newValue, oldValue) => {
	console.log('newValue' : newValue);
  	console.log('oldValue' : oldValue);
})
</script>

newValue, oldValue λͺ¨λ‘ 같은 객체λ₯Ό λ°”λΌλ³΄λ―€λ‘œ, countκ°€ 1둜 변경될 λ•Œ newValue, oldValue λͺ¨λ‘ 1을 좜λ ₯ν•œλ‹€.





πŸ“Œ 2. deep/immediate option

deepκ³Ό immediateλŠ” watch 였브젝트의 μ˜΅μ…˜μ΄λ‹€.
deep : μ§€μ •ν•œ 속성 μ•ˆμ— 있으며, μ§€μ •ν•œ μ†μ„±μ˜ 속성 값도 κ°μ‹œν•œλ‹€.
immediate : watch의 처리λ₯Ό νŽ˜μ΄μ§€λ₯Ό μ΅œμ΄ˆμ— μ¦‰μ‹œ μ‹€ν–‰ν•œλ‹€.

1. deep

deep은, μ§€μ •ν•œ μ†μ„±μ•ˆμ— μžˆλŠ” μ†μ„±μ˜ 값도 κ°μ‹œν•˜κ²Œ ν•˜λŠ” watch의 μ˜΅μ…˜μ΄λ‹€.

λ°˜μ‘ν˜• 객체λ₯Ό 직접 watch() ν•˜λ©΄ μ•”μ‹œμ μœΌλ‘œ κΉŠμ€ κ°μ‹œμžκ°€ μƒμ„±λœλ‹€. 즉, 속성 λΏλ§Œμ•„λ‹ˆλΌ λͺ¨λ“  μ€‘μ²©λœ 속성에도 νŠΈλ¦¬κ±°λœλ‹€.

μ˜ˆμ‹œλ₯Ό 톡해 μ‚΄νŽ΄λ³΄μž.

✨ 예제 5
const person = reactive({
  name: '홍길동',
  age: 30,
  hobby: 'μš΄λ™',
  obj: {
    count: 0,
  },
});

watch(person, (newValue) => {
  console.log('newValue: ', newValue);
});

person객체의 objμ†μ„±μ˜ countκ°€ λ³€κ²½λ˜μ–΄λ„, 이λ₯Ό κ°μ§€ν•˜μ—¬ μ½˜μ†”μ°½μ— 좜λ ₯λœλ‹€.




λ‹€λ§Œ, getterν•¨μˆ˜λ‘œ 객체λ₯Ό λ„˜κΈΈ κ²½μš°μ—λŠ” 객체의 값이 λ°”λ€” κ²½μš°μ—λ§Œ 트리거 λœλ‹€. μ€‘μ²©λœ 속성은 트리거 λ˜μ§€ μ•ŠλŠ”λ‹€.

μœ„μ—μ„œ μš°λ¦¬λŠ” 객체의 속성을 첫번째 λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš©ν• λ•Œ watchκ°€ λ™μž‘ν•˜μ§€ μ•Šμ•„ getterν•¨μˆ˜λ₯Ό μ‚¬μš©ν–ˆμ—ˆλ‹€.

watch(
	() => person.obj,
	(newValue) => {
		// 객체의 값이 λ°”λ€” κ²½μš°μ—λ§Œ 트리거 λœλ‹€.
	}
);

이 경우, obj의 속성인 countκ°€ λ³€κ²½λ˜μ–΄λ„ watchκ°€ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€. objμžμ²΄κ°€ 변경될 λ•Œλ§Œ λ™μž‘ν•œλ‹€.
ex) obj: "Hello!" 둜 objκ°€ 변경됐을 κ²½μš°μ—λ§Œ λ™μž‘.

deep μ˜΅μ…˜μ„ μ‚¬μš©ν•˜λ©΄ κΉŠμ€ κ°μ‹œμžλ‘œ κ°•μ œν•  수 μžˆλ‹€.

✨ 예제 6

watch(
  () => person.obj,
  (newValue) => {
    console.log('newValue: ', newValue);
  },
  { deep: true } //λ§ˆμ§€λ§‰ λ§€κ°œλ³€μˆ˜
);



2. immediate

immediateλŠ” μ΅œμ΄ˆμ— μ¦‰μ‹œμ‹€ν–‰ ν•˜κ²Œ ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€.

watchλŠ” λ°˜μ‘ν˜• 데이터λ₯Ό κ°μ‹œν•˜λ‹€κ°€, λ°˜μ‘ν˜• λ°μ΄ν„°μ˜ λ³€ν™”λ₯Ό κ°μ§€ν–ˆμ„ λ•Œ 콜백 ν•¨μˆ˜κ°€ μ‹€ν–‰λœλ‹€.
ν•˜μ§€λ§Œ, immeditate μ˜΅μ…˜μ„ μ‚¬μš©ν•˜λ©΄ μ΅œμ΄ˆμ— νŽ˜μ΄μ§€λ₯Ό μ½μ—ˆμ„ λ•Œ μ¦‰μ‹œμ‹€ν–‰ν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€.

✨ 예제 7

const message = ref('Hello World!');
const reverseMessage = ref('');

watch(
  message,
  (newValue) => {
    reverseMessage.value = newValue.split('').reverse().join('');
  },
  {
    immediate: true,
  }
);

immditate μ˜΅μ…˜μ„ 주지 μ•Šμ•˜μ„ λ•ŒλŠ”, message의 변경이 μ—†μ—ˆμœΌλ―€λ‘œ reverseMessage의 값도 μ—¬μ „νžˆ ''이닀.

message에 변경이 μžˆμ–΄μ•Όλ§Œ reverseMessage에 '!dlroW olleH'κ°€ λ‹΄κΈ΄λ‹€.

ν•˜μ§€λ§Œ, immediate μ˜΅μ…˜μ„ true둜 μ£Όλ©΄ νŽ˜μ΄μ§€κ°€ 졜초 λ‘œλ“œλ λ•Œ μ¦‰μ‹œμ‹€ν–‰λ˜μ–΄ λ°”λ‘œ reverseMessage에 '!dlroW olleH'κ°€ λ‹΄κΈ΄λ‹€.


🚫 μ£Όμ˜μ‚¬ν•­

deep μ˜΅μ…˜μ€ 큰 데이터 κ΅¬μ‘°μ—μ„œ μ‚¬μš©ν•  λ•Œ λΉ„μš©μ΄ 많이 λ“€ 수 μžˆλ‹€. ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©ν•˜κ³  μ„±λŠ₯ 영ν–₯에 μ£Όμ˜ν•΄μ•Όν•œλ‹€.




3. computec VS watch

computed와 watchλŠ” λΉ„μŠ·ν•œ 역할을 μˆ˜ν–‰ν•œλ‹€.

//computed
 computed(() =>
  message.value.split('').reverse().join('')
 );

//watch
watch(
  message,
  (newValue) => {
    reverseMessage.value = newValue.split('').reverse().join('');
  }
);
  • computed
    Vue μΈμŠ€ν„΄μŠ€μ˜ μƒνƒœ(ref, reactive λ³€μˆ˜)의 쒅속 관계λ₯Ό μžλ™μœΌλ‘œ μ„ΈνŒ…ν•˜κ³ μž ν•  λ•ŒλŠ” computed둜 κ΅¬ν˜„ν•˜λŠ” 것이 μ’‹λ‹€.
    μœ„ μ˜ˆμ‹œ 처럼 reverseMessageλŠ” message 값에 따라 κ²°μ •λ˜μ–΄μ§€λŠ” 쒅속관계에 μžˆλ‹€. 이 쒅속관계 μ½”λ“œκ°€ λ³΅μž‘ν•΄μ§€λ©΄ watch둜 κ΅¬ν˜„ν•  경우 더 λ³΅μž‘ν•΄μ§€κ±°λ‚˜ 쀑볡계산 λ˜λŠ” 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆλ‹€.

  • watch
    Vue μΈνŠΈν„΄μŠ€μ˜ μƒνƒœ(ref, reactive λ³€μˆ˜)의 λ³€κ²½ μ‹œμ μ— νŠΉμ • μ•‘μ…˜(call api, push route λ“±)을 μ·¨ν•˜κ³ μž ν• λ•Œ μ ν•©ν•˜λ‹€.
    λŒ€κ²Œμ˜ 경우 computed둜 κ΅¬ν˜„ κ°€λŠ₯ν•œ 것이라면 watchκ°€ μ•„λ‹ˆλΌ computed둜 κ΅¬ν˜„ν•˜λŠ”κ²Œ λŒ€λΆ€λΆ„ μ˜³λ‹€.



πŸ“Œ 3. watchEffect

WatchEffectλŠ” 콜백 ν•¨μˆ˜ μ•ˆμ˜ λ°˜μ‘μ„± 데이터에 λ³€ν™”κ°€ κ°μ§€λ˜λ©΄ μžλ™μœΌλ‘œ λ°˜μ‘ν•˜μ—¬ μ‹€ν–‰ν•œλ‹€.
그리고 WatchEffect의 μ½”λ“œλŠ” μ»΄ν¬λ„ŒνŠΈκ°€ 생성될 λ•Œ μ¦‰μ‹œ μ‹€ν–‰λœλ‹€.

μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ³΄μž.

✨ 예제 8

const message = ref('');

watchEffect(()=> {
	console.log(message.value);
})

μœ„μ˜ μ˜ˆμ‹œμ˜ 경우, message λ°˜μ‘ν˜• 데이터가 변경될 λ•Œλ§ˆλ‹€ μ½˜μ†”μ΄ 좜λ ₯λœλ‹€.
콜백 ν•¨μˆ˜ μ•ˆμ˜ λ°˜μ‘ν˜• 데이터가 λ³€κ²½λ˜λ©΄ μžλ™μœΌλ‘œ κ°μ§€ν•˜μ—¬ μ‹€ν–‰λ˜λŠ” 것이닀.

이것은 μ–Έμ œ μ‚¬μš©ν• κΉŒ?
μžλ™μ €μž₯ κΈ°λŠ₯을 λ§Œλ“ λ‹€κ³  μƒκ°ν•΄λ³΄μž.

save() 둜 μ €μž₯ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄ 놓고, 이와 같이 watchEffectλ₯Ό μ‚¬μš©ν•˜λŠ” 것이닀.

const message = ref('');

watchEffect(()=> {
	save(message.value);
})

μœ„μ™€ 같이 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄, λ‚΄μš©μ΄ μˆ˜μ •λ λ•Œλ§ˆλ‹€ μžλ™μœΌλ‘œ μ €μž₯ν•¨μˆ˜ save()κ°€ μ‹€ν–‰λœλ‹€.

TIP! λ°”μΈλ”©λœv-model에 .lazy μ˜΅μ…˜μ„ μ€€λ‹€λ©΄ ν¬μ»€μŠ€κ°€ μ΄λ™λ˜μ—ˆμ„λ•Œ μ €μž₯ν•˜λŠ” λ°©μ‹μœΌλ‘œλ„ λ³€κ²½ν•  수 μžˆμ„ 것이닀.


watch VS watchEffect

watch와 watchEffect λ‘˜ λ‹€ κ΄€λ ¨ μž‘μ—…(api call, push route λ“±)을 λ°˜μ‘μ μœΌλ‘œ μˆ˜ν–‰ν•  수 있게 ν•΄μ€€λ‹€. ν•˜μ§€λ§Œ μ£Όμš”ν•œ 차이점은 κ΄€λ ¨λœ λ°˜μ‘ν˜• 데이터λ₯Ό μΆ”μ ν•˜λŠ” 방식이닀.

  • watch
    λͺ…μ‹œμ μœΌλ‘œ κ΄€μ°°λœ μ†ŒμŠ€(첫번째 λ§€κ°œλ³€μˆ˜)만 μΆ”μ ν•œλ‹€. 콜백 λ‚΄μ—μ„œ μ•‘μ„ΈμŠ€ν•œ ν•­λͺ©μ€ μΆ”μ ν•˜μ§€ μ•ŠλŠ”λ‹€.Β λ˜ν•œ, μ½œλ°±μ€ μ†ŒμŠ€κ°€ μ‹€μ œλ‘œ λ³€κ²½λœ κ²½μš°μ—λ§Œ νŠΈλ¦¬κ±°λœλ‹€. 콜백이 μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜λŠ” μ‹œκΈ°λ₯Ό 보닀 μ •ν™•ν•˜κ²Œ μ œμ–΄ν•  수 μžˆλ‹€.
  • watchEffect
    콜백 내에 λ‹΄κΈ΄ λͺ¨λ“  λ°˜μ‘ 속성을 μžλ™μœΌλ‘œ μΆ”μ ν•œλ‹€. 이것은 더 νŽΈλ¦¬ν•˜κ³  일반적으둜 더 κ°„κ²°ν•œ μ½”λ“œλ₯Ό μƒμ„±ν•˜μ§€λ§Œ λ°˜μ‘μ„± 쒅속성을 덜 λͺ…μ‹œμ μœΌλ‘œ λ§Œλ“ λ‹€.



μ°Έκ³ λ¬Έν—Œ

μΈν”„λŸ° vue3 기본편 - 짐코딩
https://ko.vuejs.org/api/options-state.html#watch



였늘의 ν•œλ§ˆλ””

κ°μ²΄λ‚˜ 배열을 주둜 μ‚¬μš©ν•˜λŠ” μ‹€λ¬΄μ—μ„œ watchκ°€ 잘 λ™μž‘ν•˜μ§€ μ•ŠλŠ” κ²½μš°κ°€ λ§Žμ•˜λ‹€.
watchλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 늘 λΆˆνŽΈν–ˆμ—ˆλŠ”λ° μ΄λ ‡κ²Œ ν¬μŠ€νŒ…ν•˜κ³  λ‚˜λ‹ˆ μ œλŒ€λ‘œ 정리 된 기뢄이닀.

이 ν¬μŠ€νŒ…μ€ λ‚˜λ₯Ό μœ„ν•œ ν¬μŠ€νŒ…μ΄λ‹€.. μ•žμœΌλ‘œλ„ 자주 λ°©λ¬Έν•  λ‚˜λ₯Ό μœ„ν•΄ 응원을 μ „ν•œλ‹€! watchλ₯Ό νŽΈλ¦¬ν•˜κ²Œ 잘 μ‚¬μš©ν•  수 있기λ₯Ό!

profile
ν•˜μ΄ 이것은 λ‚˜μ˜ 깨지고 λΆ€μ„œμ§€λŠ” κΈ°λ‘λ“€μž…λ‹ˆλ‹€

1개의 λŒ“κΈ€

comment-user-thumbnail
2023λ…„ 8μ›” 15일

쒋은 κΈ€ κ°μ‚¬ν•©λ‹ˆλ‹€. 자주 λ°©λ¬Έν• κ²Œμš” :)

λ‹΅κΈ€ 달기