Throttling과 Debouncing
Throttling
Throttling은 일정 시간(window) 동안 함수 호출을 최대 1번만 실행되도록 제한할 때 유용하다.
가장 흔한 예시는 scroll 이벤트다. 사용자가 스크롤을 한 번 쭉 내리기만 해도 이벤트가 짧은 시간에 수십~수백 번 발생할 수 있다. 이때 이벤트가 발생할 때마다 핸들러를 그대로 실행하면 다음 문제가 생기기 쉽다.
- 핸들러 연산이 무거우면 렌더링이 밀리면서 프리징(버벅임) 이 발생할 수 있고
- 이벤트마다 서버 요청을 보내면 불필요한 API 호출이 폭증할 수 있다
그래서 스크롤/리사이즈처럼 “자주 발생하는 이벤트”에는 throttling이 좋은 안전장치가 된다.
참고: lodash의 throttle은 leading/trailing 같은 옵션까지 지원해 더 유연하지만, 핵심 아이디어는 비슷하다.
간단 구현 (Closure 기반)
function throttle(func, delay) {
let throttling = false;
return function() {
if (!throttling) {
throttling = true;
setTimeout(() => {
func.apply(this, arguments);
throttling = false;
}, delay);
}
};
}
mydiv.addEventListener("scroll", throttle(() => {console.log("Heavy Task...")}, 1000));Debouncing
Debouncing도 중복 호출을 줄인다는 점에서는 throttling과 같지만, 동작 방식이 다르다.
- Throttling: “2초 동안 최대 1번”처럼 주기적으로 실행을 허용
- Debouncing: 호출이 계속 들어오면 실행을 계속 미루다가, 마지막 호출 이후 delay가 지나면 1번만 실행
이 “미루기” 특성 때문에 debouncing은 보통 input 이벤트에서 많이 쓴다. 사용자가 타이핑할 때마다 검색 API를 호출하는 대신, 타이핑이 잠깐 멈춘 뒤(예: 500ms) 한 번만 요청하면 트래픽도 줄고 UX도 더 자연스럽다.
간단 구현 (closure 기반)
function debounce(func, delay) {
let timeoutId;
return function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, arguments);
}, delay);
};
}
inputField.addEventListener('input', debounce(saveData, 500));Written on
2024-09-01 06:35
