vue watchEffect cleanup 사용법: 실무 가이드와 체크리스트
vue watchEffect cleanup 사용법을 실무 관점에서 정리합니다. watchEffect에서 반환 함수로 리소스 정리, 비동기 취소 패턴, 성능·운영 주의점을 코드 예제와 체크리스트로 제공합니다.
vue watchEffect cleanup 사용법이 필요한 상황
vue watchEffect cleanup 사용법은 컴포넌트의 반응형 사이드 이펙트를 설정하고 해제할 때 필요합니다. 이 글에서는 watchEffect 내부에서 생성한 타이머, 이벤트 리스너, 비동기 작업을 안전하게 정리하는 방법과 언제 이 패턴을 사용하거나 피해야 하는지, 실무 적용 가능한 코드 예제와 체크리스트를 제공합니다.
vue watchEffect cleanup 사용법 핵심 개념
watchEffect는 반응형 종속성을 자동 추적해 콜백을 재실행합니다. 이 콜백은 반환값으로 cleanup 함수를 제공할 수 있고, 해당 함수는 다음 실행 직전 또는 컴포넌트 언마운트 시에 호출됩니다. cleanup은 메모리 누수와 중복 작업을 방지하는 표준 패턴입니다.
핵심 포인트:
- watchEffect 콜백에 반환 함수(register cleanup) 작성
- 반환 함수는 이전 이펙트를 정리하는 역할
- 비동기 취소(token/flag/AbortController)와 함께 사용
vue watchEffect cleanup 사용법 실무 예제
아래 예제는 타이머와 fetch 취소를 정리하는 실무 패턴입니다.
// 예제: 타이머와 Fetch 취소를 함께 정리 import { ref, watchEffect, onMounted } from 'vue' export default { setup() { const query = ref('') const data = ref(null) const loading = ref(false) watchEffect((onCleanup) => { // 이전 작업 정리용 플래그/컨트롤러 const controller = new AbortController() loading.value = true // 비동기 작업 fetch(`/api/search?q=${encodeURIComponent(query.value)}`, { signal: controller.signal }) .then((r) => r.json()) .then((json) => { data.value = json }) .catch((e) => { if (e.name === 'AbortError') return console.error(e) }) .finally(() => { loading.value = false }) // 타이머 사용 예시 const id = setTimeout(() => { /* debounce-like side effect */ }, 300) // cleanup 등록: 이전 fetch 취소 및 타이머 클리어 onCleanup(() => { controller.abort() clearTimeout(id) }) }) return { query, data, loading } } }
위 패턴에서 핵심은 onCleanup(또는 watchEffect의 인자로 제공되는 onCleanup)을 사용해 반드시 정리 코드를 등록하는 것입니다. onCleanup 이름은 watchEffect 콜백 인자에 제공된 함수를 활용할 수 있습니다.
언제 쓰면 좋고 언제 피해야 할까
언제 쓰면 좋은가:
- 반응형 값 변경에 따라 외부 리소스(타이머, 이벤트, fetch 등)를 생성/갱신할 때
- 컴포넌트 언마운트 시 리소스 정리가 필요할 때
- 중복 실행을 방지해야 할 때(디바운스, 중복 네트워크 호출 등)
언제 피해야 하는가:
- 순수 계산(부수효과가 없는 것)만 하는 경우(reactive 계산은 computed 사용)
- 리소스가 컴포넌트 수명과 무관하게 전역(singleton)으로 유지되어야 할 때
- 정리 로직을 지나치게 복잡하게 만들어 가독성을 해치는 경우
비교: cleanup 패턴 선택 기준
다음 표는 watchEffect에서 정리 패턴(간단한 클리어 vs AbortController vs 외부 라이브러리 취소)을 비교한 기준표입니다.
| 구분 | 항목1 | 항목2 | 항목3 |
|---|---|---|---|
| 내용 | 간단한 clearTimeout/clearInterval | AbortController로 fetch 취소 | 외부 라이브러리(axios cancel/token) |
설명:
- 간단한 clearTimeout/clearInterval: 브라우저 타이머 정리에 적합, 구현이 단순
- AbortController: 표준 Fetch API 취소, 네트워크 요청 취소가 필요할 때 권장
- 외부 라이브러리 취소: axios 등 라이브러리별 취소 API 사용 필요
실무 체크리스트
- 모든 watchEffect에서 side-effect 생성 시 onCleanup 등록 여부 확인
- 비동기 요청은 취소 가능한 방식(AbortController 또는 라이브러리 제공 취소)으로 구현
- 타이머와 이벤트 리스너는 항상 clear/remove 처리
- 중첩된 watchEffect가 있는지 여부와 중복 정리 로직 존재 여부 점검
- 단위 테스트 및 통합 테스트에서 언마운트 시 정리 확인
체크리스트(간단):
- onCleanup로 모든 정리 코드 등록
- fetch는 AbortController 사용
- 타이머/이벤트는 반드시 clear/remove
- 중복 실행 방지 로직(디바운스/스로틀) 적용
성능·보안·운영 주의점
성능:
- 불필요한 watchEffect 재실행은 렌더 및 네트워크 트래픽을 증가시킴. 종속성 원인을 최소화하고, 필요 시 watch 대신 watch를 세분화하거나 computed 사용 고려.
- cleanup이 제대로 동작하지 않으면 메모리 누수와 누적된 타이머/리스너로 성능 저하 발생.
보안:
- 네트워크 요청을 취소하더라도 민감한 입력 값 로깅이나 에러 전송 시 개인정보가 포함되지 않도록 주의.
운영:
- 서버 호출 취소가 잦아도 서버에서 장기 처리 작업이 남지 않도록 백엔드와 협의.
- 에러/취소 통계(예: abort 발생 빈도)를 수집해 UX 개선 포인트로 활용.
vue watchEffect cleanup 사용법 심화 팁
- debounce를 원하면 watch 대신 명시적 debounce util 사용 후 onCleanup으로 타이머 정리
- 복수 비동기 작업이 있을 때는 각 작업별 컨트롤러를 생성해 개별 취소 가능하도록 설계
- 외부 상태 라이브러리와 조합 시 전역 취소 로직과 컴포넌트 로컬 취소 로직 경계 명확화
자주 묻는 질문
Q1: watchEffect에서 onCleanup을 여러 번 호출해도 되나요? A1: 네. watchEffect 콜백 내에서 onCleanup을 여러 번 호출해도 모두 등록됩니다. 다만 관리 편의상 하나의 cleanup 함수로 묶어 등록하는 것을 권장합니다.
Q2: watch 대신 watchEffect를 써야 할까요? A2: watchEffect는 종속성이 자동 추적되는 상황에서 편리합니다. 특정 ref/prop만 추적하고 싶다면 watch를 사용해 명시적으로 종속성을 제한하는 것이 더 안전할 수 있습니다.
Q3: AbortController가 모든 브라우저에서 동작하나요? A3: 현대 브라우저에서는 대부분 지원하지만, 구형 브라우저 호환이 필요하면 폴리필이나 axios 같은 라이브러리의 취소 기능을 사용하세요.
Q4: cleanup이 실행되는 시점은 언제인가요? A4: watchEffect의 반환 cleanup은 다음 실행 직전과 컴포넌트 언마운트 시에 호출됩니다.
정리
- watchEffect 내부에서 onCleanup으로 정리 코드를 등록해 리소스 누수를 방지하세요.
- 비동기 요청은 AbortController 등 취소 가능한 방식으로 구현하고, 타이머/이벤트는 항상 clear/remove하세요.
- 불필요한 재실행을 줄이기 위해 종속성을 관리하거나 watch를 고려하세요.
- 체크리스트로 구현·테스트·운영 단계에서 cleanup 적용을 확인하세요.