Throttle과 Debounce의 등장 배경
Throttle
과 Debounce
는 DOM 이벤트를 제어하는 방법으로 자주 호출되는 이벤트의 실행 빈도를 줄여 성능상의 이점을 얻기 위해 사용한다.
Throttle과 debounce를 사용할 수 있는 대표적인 상황은 아래와 같다.
- 스크롤링을 통한 데이터 노출
- 검색어 입력시 자동완성
예를 들어 스크롤 이벤트를 감지하여 API를 호출해 데이터를 가져오고자 하는 상황이라고 가정해보자. 이때, 사용자가 스크롤을 움직일 때마다 수많은 스크롤 이벤트가 발생할 것이고 이는 수많은 API 호출로 이어질 것이다. 매번 스크롤 이벤트에 대한 콜백이 발생하고 해당 콜백의 수행은 매우 큰 리소스를 차지하게 된다. 이는 결국 서비스의 성능과 사용자의 경험 저하를 야기하게 된다.
이러한 문제를 해결하기 위해 Throttle
과 Debounce
는 이벤트 핸들러가 한번에 많은(연속적인) 연산을 수행하는 경우에 대해 제약을 걸어 제어할 수 있는 수준으로 이벤트를 발생시키는 것을 목표로 한다.
Throttle과 Debounce의 기본 개념
Throttle과 Debounce의 기본 개념은 아래와 같다.
- Throttle : 일정한 주기마다 이벤트를 발생시킨다
- ⇒ 일정시간 동안 이벤트를 한번만 실행
- Debounce : 특정 시간이 지난 뒤에 하나의 이벤트만 발생시킨다
- ⇒ 여러번 발생하는 이벤트에서 가장 마지막 이벤트만 실행
사용 예시
간단한 예시와 함께 살펴보면 다음과 같다.
input의 입력에 따라 자동완성 API를 호출하는 경우
- Throttle: 500ms 마다 api를 호출한다.
- Debounce: 입력이 끝난 후 api를 호출한다.
<input id="search" type="search" name="search" value="" />
let debounce = null;
let throttle = null;
function keyUpFn(el) {
// normal
console.log('normal', el.target.value, new Date().getTime());
// throttle
if(!throttle) {
setTimeout(() => {
console.log('throttle', throttle, new Date().getTime());
throttle = null;
}, 500);
}
throttle = el.target.value;
// debounce
clearTimeout(debounce);
debounce = setTimeout(() => {
console.log('debounce', el.target.value, new Date().getTime());
}, 500);
}
document.getElementById("search").addEventListener('keyup', keyUpFn);
See the Pen Untitled by pebble (@pebblepark) on CodePen.
Throttle
let throttle = null; // event function 밖에서 선언 및 초기화
// event function 내부에서 실행
if(!throttle) {
setTimeout(() => {
console.log('throttle', throttle, new Date().getTime());
throttle = null;
}, 500);
}
throttle = el.target.value;
코드를 통해 살펴본 Throttle은 이벤트 발생시
throttle
이 존재하지 않으면 5초 이후에 throttle을 null로 초기화한다. (비동기)throttle
에 현재 입력 값을 넣어준다.
throttle
이 존재하지 않는 경우에 setTimeout()으로 일정 주기 이후에 throttle을 null로 초기화해준다. 이때 일정 주기 이후에 초기화되는 것은 비동기이기 때문에 throttle이 null로 초기화되기 이전에 입력 값이 세팅된다.- 이후 이벤트가 호출되어도 throttle에 값이 존재하기 때문에 throttle의 값이 업데이트 되는 것 외에는 아무일도 일어나지 않는다.
- setTimeout()에서 설정한 주기가 지나면 로직을 수행하고 throttle의 값이 null로 초기화된다. 예제에서는 콘솔에 로그를 찍었지만 실제로는 api를 호출하는 등의 로직을 작성해준다.
- 따라서 처음 이벤트가 발생한 이후로 setTimeout()으로 설정한 주기가 지나야 로직이 한 번 실행되는 것을 보장한다.
Debounce
let debounce= null; // event function 밖에서 선언 및 초기화
// event function 내부에서 실행
clearTimeout(debounce);
debounce = setTimeout(() => {
console.log('debounce', el.target.value, new Date().getTime());
}, 500);
코드를 통해 살펴본 Debounce는 이벤트 발생시
debounce
를 clear 한다.- 5초 이후에 로직을 수행한다. (비동기)
- clearTimeout() 을 통해서
debounce
를 취소한다. - setTimeout()으로 설정한 주기가 지나면 로직을 수행한다.
- setTimeout()으로 설정한 주기에 도달하기 전 이벤트가 발생하면 이전 debounce 함수 실행을 취소하고 다시 setTimeout()으로 설정한 주기를 기다린다.
Throttle과 Debounce의 차이점
- Throttle은 일정한 주기마다 실행을 보장한다.
- 반면, Debounce는 일정한 주기에 도달하기 전 이벤트가 계속 발생할 경우, 맨 마지막 이벤트를 제외한 이전 이벤트들은 모두 무시된다.
참고
https://webclub.tistory.com/607
https://pks2974.medium.com/throttle-와-debounce-개념-정리하기-2335a9c426ff
'Frontend' 카테고리의 다른 글
Intersection Observer API를 활용한 무한스크롤 구현 (0) | 2022.08.17 |
---|---|
React-Query 정리 (0) | 2022.08.05 |
[Redux] 간단한 예제로 살펴보는 리덕스의 동작 원리 (0) | 2022.03.17 |
[React] ContextAPI & useContext Hook을 통한 Global State 값 관리하기 (0) | 2022.03.11 |
[Javascript] 변수, 호이스팅, TDZ (0) | 2022.03.07 |