이벤트를 효율적으로 다루기 위한 debouce를 알아보자.
디바운스?
디바운스는 실행되는 이벤트들 중 마지막 이벤트만 실행한다.
mousemove, scroll 등, 이벤트가 발생될 때 과도한 이벤트의 발생을 막기 위해 디바운스와 스로틀을 이용하여 이벤트 발생을 제어한다.
예를 들어,
// 이렇게 코드를 짜고 마우스를 움직이면 아주 조그마한 움직임에도 수십번의 'hi'가 찍히는 것을 콘솔창에서 확인할 수 있다.
document.addEventListener('mousemove', () => console.log('hi'));
이런 과도한 이벤트의 발생은 브라우저의 성능을 저하시킨다.
또 다른 예로,
이 코드는 사용자가 값을 입력할 때 마다 콘솔창에 인풋값을 보여준다.
<body>
<input type="text" class="input" />
</body>
<script>
input.addEventListener('input', ({ target }) => console.log(target.value));
</script>
/* 결과
* input: 'h' return: 'h'
* input: 'hi' return: 'hi' <--- the result a developer wants
*/
이러한 경우에 사용자가 입력을 마친 이후의 값을 필요로 한다면,
마지막 이벤트를 제외한 나머지는 불필요한 이벤트의 발생이다.
Debounce를 이용하여 이벤트를 제어해보자.
// 1초 이내에 입력을 하면 console에 인풋값을 출력하지 않는다.
let timer;
input.addEventListener('input', ({target}) => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log('입력:', target.value);
}, 1000);
});
};
유틸함수로 debounce 사용하기
const main = () => {
const input = document.querySelector('.input');
const ms = 1000;
const debounce = (fn, ms) => {
let timer;
return (e) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn(e);
}, ms);
};
};
const printInputValue = ({ target }) => console.log(target.value);
const inputHandler = debounce((e) => printInputValue(e), ms);
input.addEventListener('input', inputHandler);
};
main();
작동원리: input 이벤트가 발생 -> inputHandler -> debounce(콜백함수, ms)
debounce 내의 timer를 통해 printInputValue 함수를 제어한다.
현재는 단순히 input의 값을 제어하기 위한 debounce 함수를 만들었다.
더 나아가 fetch, promise와 조합해 범용성 있는 유틸을 만들어 볼 예정이다.