- 발행일
[ZBF]7주차 보충 : debounce와 throttle의 개념
[ZBF]7주차 보충 : debounce와 throttle의 개념
이 글은 네이버 블로그에 2024년 6월 30일에 올렸던 것을 그대로 옮겨온 것입니다.
debounce와 throttle은 짧은 시간 동안 빈번하게 발생하는 이벤트의 처리를 제어하여 성능을 최적화하는 기술입니다.
- Debounce: 연이어 발생하는 이벤트 중 마지막 이벤트만을 처리합니다. 예를 들어, 키보드 입력 이벤트에서 debounce를 사용하면 사용자가 입력을 멈추고 일정 시간이 지난 후에만 이벤트가 처리됩니다.
- Throttle: 일정 간격으로 이벤트를 처리합니다. 예를 들어, 스크롤 이벤트에서 throttle을 사용하면 지정한 간격으로 이벤트가 발생하여 과도한 이벤트 처리를 방지합니다.
차이점
- Debounce: 마지막 이벤트만 처리합니다.
- Throttle: 처음 이벤트가 발생한 후 일정 간격으로 이벤트를 처리합니다.
웹 성능 최적화
예시: 키보드 입력 이벤트
- Debounce: 사용자가 입력할 때마다 API 호출이 발생하면 성능 저하가 발생할 수 있습니다. debounce를 사용하면 사용자가 입력을 멈추고 일정 시간이 지난 후에 API 호출이 발생하여 불필요한 호출을 줄일 수 있습니다.
function debounce(func, delay) {
let debounceTimer;
return function() {
const context = this;
const args = arguments;
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => func.apply(context, args), delay);
}
}
예시: 스크롤 이벤트
- Throttle: 스크롤 이벤트가 빈번하게 발생하면 성능 저하가 발생할 수 있습니다. throttle을 사용하면 일정 간격으로 이벤트를 처리하여 성능을 최적화할 수 있습니다.
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
키보드 입력 이벤트: 자동완성 검색 기능을 구현할 때, 사용자가 입력할 때마다 API 요청이 발생하여 서버에 과도한 부하가 걸리는 문제가 있었습니다. 이를 해결하기 위해 debounce를 사용했습니다.
장점: 불필요한 API 호출을 줄여 서버 부하를 줄일 수 있었습니다.
단점: 입력 후 일정 시간 동안 대기해야 결과가 나타나므로 사용자 경험이 약간 지연될 수 있습니다.
스크롤 이벤트: 웹페이지에서 무한 스크롤 기능을 구현할 때, 스크롤 이벤트가 너무 자주 발생하여 브라우저의 렌더링 성능이 저하되는 문제가 있었습니다. 이를 해결하기 위해 throttle을 사용했습니다.
장점: 이벤트 처리 빈도를 줄여 브라우저 렌더링 성능을 개선할 수 있었습니다.
단점: 첫 번째 이벤트와 그 이후 이벤트 사이의 간격 동안에 발생한 이벤트가 무시될 수 있습니다.
// Debounce function
function debounce(func, delay) {
let debounceTimer;
return function() {
const context = this;
const args = arguments;
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => func.apply(context, args), delay);
}
}
// Throttle function
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
// Usage examples
const handleInputChange = debounce((event) => {
// API call
console.log('API call with:', event.target.value);
}, 500);
const handleScroll = throttle(() => {
console.log('Scroll event handled');
}, 200);
document.getElementById('inputField').addEventListener('input', handleInputChange);
window.addEventListener('scroll', handleScroll);