일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- axios
- 원리
- DoM
- 백준
- virtual Dom
- Hook
- BOJ
- 개발
- State
- 가상 DOM
- 요청
- 상태 끌어올리기
- 프로그래머스
- Java
- API
- LeetCode
- 유용한 사이트
- EventListener
- 프로젝트
- programmers
- javascript
- deep
- Dive
- 상태
- memory
- 꿀팁
- react
- Today
- Total
탄탄한 기본기!
javaScript - 디바운스(debounce), 스로틀(throttle) 본문
디바운스와 스로틀은 scroll, resize, input, mousemove 같은 짧은 간격으로 연속적으로 이벤트를 발생시키는 경우에 과도한 이벤트 발생을 방지하는 기법이다.
1. 디바운스(debounce)
예를 들어서 click 같은 경우에 오토 마우스같은 툴을 사용해서 1초에 10번씩, 혹은 사람의 손으로 소위 말하는 '광클'로 클릭 이벤트를 1초에 1번 이상 발생시킬 수 있다. 하지만 이러한 클릭 이벤트를 조절하고 싶을 때, 디바운스라는 기법을 사용할 수 있다.
디바운스는, 엘리베이터를 생각하면 이해하기 쉽다(https://css-tricks.com/debouncing-throttling-explained-examples/). 엘리베이터를 타고 문이 닫히려고 할 때, 누군가 열림 버튼(이벤트 발생)을 누른다면 엘리베이터는 출발하지 않고 다시 대기한다. 이러한 원리와 마찬가지이다.
만약 2초를 기준으로 정했을 때, 이벤트가 발생한 후 2초 내에 클릭 이벤트가 발생하지 않았을 경우에 마지막 이벤트를 인정하는 것이다. 만약 첫 번째 이벤트를 발생시키고, 1초 후에 다시 이벤트를 발생시키면 다시 2초를 기다리고, 만약 그 시간 안에 다시 이벤트가 발생하지 않았다면 마지막 이벤트를 이벤트로 인정하는 것이다.
위에서 든 클릭 이벤트를 예시로 들면 아래와 같다.
const debounce = (callback, delay) => {
let timerId; // setTimeOut이 걸려있을 때 이를 해제하기 위해서 저장하고 있는 '자유변수'
return event => {
// 핵심. 만약 지정한 delay가 지나기 전에(callback이 실행되기 전에) 다시 이벤트가 발생한다면
// 해당 이벤트를 취소하고 그 시간부터 다시 시간을 재며 새로이 이벤트를 발생시킨다.
if (timerId) clearTimeout(timerId);
timerId = setTimeout(callback, delay, event);
};
};
// 0.5초 안에 클릭을 다시하면 이전의 이벤트는 취소되고 다시 새로운 이벤트를 생성한다.
$buttonElement.addEventListener('click', debounce(() => {
console.log('clicked');
}, 500));
하지만 위의 debounce함수는 완전하지 않고 간략하게 예제를 이해할 수만 있도록 해놓은 간단한 코드이기 때문에 실제 프로젝트에서는 Lodash나 Underscore의 debounce라이브러리를 사용하는 것이 좋을 것이다.
2. 스로틀(throttle)
스로틀은 디바운스와 과도한 이벤트를 방지한다는 점에서 비슷하지만, 내부 동작이 약간 다르다.
위에서 예시로 든 2초로 설정된 디바운스의 경우에 1초마다 계속 클릭 이벤트를 발생시키면 계속 이벤트가 취소되고 새로운 이벤트가 등록되는 것을 반복해서 이벤트가 계속 동작하지 않을 것이다.
하지만 스로틀은 지정한 delay 시간을 정해놓고, 그 시간동안의 모든 이벤트들을 하나로 묶어 무조건 발생시킨다. 즉, 만약 스로틀의 delay시간을 2초로 지정했다면 최초로 이벤트를 발생시키고, 2초 안에 발생한 모든 이벤트들을 하나로 묶어 해당 이벤트를 발생시킨다.
const throttle = (callback, delay) => {
let timerId;
return event => {
if (timerId) return;
timerId = setTimeout(
() => {
callback(event);
timerId = null;
},
delay,
event
);
};
};
$buttonElement.addEventListener(
'click',
throttle(() => {
console.log('clicked');
}, 500)
);
위 코드를 보면, throttle함수에서 만약 예약된 이벤트가 있다면(timerId) 그냥 무시하도록 하고, 지정해준 delay시간이 지난 후에 콜백 함수를 그대로 실행한 후 timerId를 다시 초기화해서 다음 이벤트 등록을 허락한다.
'개인 공부 > JS (자바스크립트)' 카테고리의 다른 글
Promise 내부 구현 따라해보기 (0) | 2021.07.02 |
---|---|
javaScript - Ajax (0) | 2021.06.27 |
DOM(Document Object Model) - HTMLCollection과 NodeList (0) | 2021.06.06 |
javaScript - Set과 Map (0) | 2021.06.03 |
javaScript - 이터러블과 이터레이터 (0) | 2021.06.01 |