Reese-log
  • About
  • Blog

© 2025 Reese. All rights reserved.

2023년 2월 1일

Vue3의 watch / watchEffect

#Vue

watch vs watchEffect – Vue 3 Composition API에서의 반응형

Vue 3 Composition API에서는 반응형 데이터의 변화를 감시하기 위해 watch와 watchEffect 두 가지 기능을 제공합니다.

두 도구는 유사해 보이지만, 동작 방식, 실행 시점, 사용 목적에서 뚜렷한 차이가 있습니다.

공통점

항목watchwatchEffect
Vue 3에서만 사용 가능❌ (Vue 2에서도 Options API 기반 사용 가능)✅ Composition API 전용
Composition API에서 사용✅✅
반응형 데이터 감시✅✅
내부에서 side effect 처리✅✅

차이점

항목watchwatchEffect
감시 대상명시적 (ref, getter, 배열 등)암시적 (함수 내부의 종속성 추적)
실행 시점lazy (기본), immediate 옵션 가능즉시 실행 (기본)
이전 값 접근✅ 가능❌ 불가능
Side Effect 제어명확히 가능 (debounce 등)간단한 반응 처리에 유리
종속성 자동 추적❌ 수동 지정 필요✅ 자동 추적
취소 로직 (invalidate)✅ 가능✅ 가능

watch – 명시적 감시와 비교가 필요한 경우 사용

주요 특징

  • 감시 대상(ref, reactive 속성, getter 등)을 명시적으로 지정
  • 변경 전후 값(newVal, oldVal) 을 확인 가능
  • 비동기 작업, debounce/throttle 처리에 적합
  • 사용 예제 1: 기본 구조

    typescript
    1import { ref, watch } from 'vue'
    2
    3const count = ref(0)
    4
    5watch(count, (newVal, oldVal) => {
    6  console.log(`count changed from ${oldVal} to ${newVal}`)
    7})

    사용 예제 2: getter 사용

    typescript
    1watch(
    2  () => user.value.name,
    3  (newName, oldName) => {
    4    console.log(`user name changed from ${oldName} to ${newName}`)
    5  }
    6)

    사용 예제 3: 여러 개 감시

    typescript
    1watch(
    2  [() => a.value, () => b.value],
    3  ([newA, newB], [oldA, oldB]) => {
    4    console.log('a or b changed')
    5  }
    6)

    옵션 사용

    typescript
    watch(count, callback, {
      immediate: true,      // mount 시에도 실행
      deep: true,           // 객체/배열의 내부 변경 감지
    })

    watchEffect – 선언형 방식의 반응 처리

    주요 특징

  • 감시 대상을 명시하지 않음
  • 함수 내부에서 사용한 모든 ref/ reactive가 자동 추적 대상이 됨
  • 즉시 실행됨
  • oldValue를 알 필요 없고, 단순한 반응형 사이드 이펙트를 다룰 때 적합
  • 기본 예제

    typescript
    1import { watchEffect, ref } from 'vue'
    2
    3const count = ref(0)
    4
    5watchEffect(() => {
    6  console.log(`The current count is ${count.value}`)
    7})
    count.value가 바뀔 때마다 자동으로 실행

    여러 종속성 추적

    typescript
    watchEffect(() => {
      console.log(`User: ${user.value.name}, Profile: ${profile.value.job}`)
    })
    user 또는 profile 내부 속성 중 하나라도 바뀌면 실행됨

    실전 사용 기준 – 언제 어떤 걸 써야 하나?

    상황사용 추천
    데이터 변경 전후 비교가 필요한 경우watch
    감시 대상이 복잡하고 명시적으로 지정해야 하는 경우watch
    즉시 실행 + 여러 반응형 데이터 추적 + oldValue 불필요watchEffect
    간단한 반응형 연산 또는 side effect (ex. 콘솔 출력, fetch)watchEffect
    비동기 처리에 대한 취소 로직이 필요한 경우watch (with onInvalidate)

    ⚠️ 주의: watchEffect는 모든 변경에 민감하다

    typescript
    watchEffect(() => {
      console.log(`Hello ${user.value.name}`)
    })

    위 코드는 user 객체가 다시 할당되거나 내부 속성이 바뀌면 무조건 실행됨.

    너무 많은 데이터를 감지하거나 무거운 로직을 넣으면 불필요한 리렌더링이 발생할 수 있음.

    복잡한 연산이나 비동기 처리에는 watch가 더 적절합니다.

    Bonus: 비동기 작업 처리 시 onInvalidate

    typescript
    1watch(query, async (newQuery, _, onInvalidate) => {
    2  let cancelled = false
    3
    4  onInvalidate(() => {
    5    cancelled = true
    6  })
    7
    8  const result = await fetchData(newQuery)
    9  if (!cancelled) {
    10    data.value = result
    11  }
    12})
    이전 요청이 완료되기 전에 새로운 요청이 들어올 경우 이전 작업을 취소할 수 있음

    정리

    항목watchwatchEffect
    Vue 버전Vue 2/3Vue 3 Composition API 전용
    감시 대상 지정✅ 명시 필요❌ 자동 추적
    실행 시점lazy (기본), immediate 가능✅ 즉시 실행
    이전 값 접근✅ 가능❌ 불가능
    종속성 추적 방식수동자동
    비동기 제어✅ onInvalidate() 가능✅ 가능하나 보통 사용하지 않음
    적합한 상황비교, 비동기, 특정 감시 대상선언적 로직, 단순 반응 처리