📋 Debounce — 이벤트 최적화 & 비동기 제어
Debounce는 짧은 시간에 연속으로 발생하는 이벤트를 하나로 묶어 처리하는 기법입니다.
이벤트가 발생할 때마다 즉시 로직을 실행하지 않고, 마지막 이벤트 이후 일정 시간이 지났을 때 단 한 번만 실행 합니다.
주로 사용자 입력 기반 이벤트 에서 발생하는 불필요한 연산, 렌더링, API 호출을 줄이기 위해 사용됩니다.
1️⃣ Debounce가 필요한 이유
브라우저에서 발생하는 이벤트 중 일부는 매우 높은 빈도로 싱행됩니다.
input,keyupscrollresizemousemove
이벤트마다 무거운 로직(API 호출, DOM 계산, 상태 업데이트)을 실행하면:
- 성능 저하
- 네트워크 낭비
- UX 저하 (버벅임)
👉 Debounce는 “이벤트 폭주(event flood)”를 제어하기 위한 패턴입니다.
2️⃣ 핵심 개념 요약
- 실행 시점: 이벤트가 끝난 후
- 기준: 마지막 호출 이후 지정된 시간 동안 호출이 없을 때
- 결과: 여러 번 발생한 이벤트 → 1회 실행
📌 키워드로 정리하면
Delay + Cancel + Last Call
3️⃣ 동작 방식 (타이머 기반)
-
이벤트 발생
-
setTimeout으로 실행 예약 -
일정 시간 내 이벤트 재발생
- 기존 타이머
clearTimeout - 새 타이머 등록
- 기존 타이머
-
이벤트가 멈추면 → 예약된 함수 실행
👉 항상 가장 마지막 이벤트만 유효
4️⃣ 기본 구현 (Vanilla JavaScript)
// 연속 호출되는 함수를 마지막 호출 기준으로 delay 후 한 번만 실행하는 debounce 유틸
function debounce(fn, delay) {
let timer = null; // 이전 실행을 취소하기 위해 타이머 ID를 클로저로 유지
return function (...args) {
clearTimeout(timer); // 이전에 예약된 실행 취소
timer = setTimeout(() => {
fn.apply(this, args); // 마지막 호출의 this와 인자를 유지해 함수 실행
}, delay);
};
}
🧐 사용 예시
const handleSearch = debounce((keyword) => {
console.log("검색:", keyword);
}, 300);
input.addEventListener("input", (e) => {
handleSearch(e.target.value);
});
- 입력 중에는 실행되지 않음
- 입력이 멈춘 후 300ms 뒤 1회 실행
5️⃣ Debounce와 비동기(Event Loop 관점)
Debounce는 비동기 패턴이 아니라 비동기 제어 패턴입니다.
- 내부적으로
setTimeout사용 setTimeout콜백은 Macrotask Queue에 등록- 연속 호출 시
clearTimeout으로 기존 task 제거 - 최종 1개의 task만 Event Loop에 남음
📌 Debounce는 Event Loop 위에서 동작하는 제어 로직입니다.