scroll,input,mousemove 같이 짧은 시간에 연속적으로 발생할 수 있는 것들이 있다. 제출버튼이 있다고 가정하자. 제출버튼을 짧은 시간안에 여러번눌러 서버요청을 여러번 보낸다고 하면 서버에 과부하가 일어날 것 이다. 이러한 이벤트들이 과도하게 발생하게되면 브라우저 성능에 매우 좋지 않다. 디바운스 (debounce) 와 스로틀 (throttle)은 과도한 이벤트 핸들러들을 핸들링하기 위한 기술이다.
debounce는 여러번 이벤트가 발생하고나서 지정한 시간동안 더이상 이벤트가 발생하지 않았을때 마지막으로 발생한 이벤트 한번만 실행하게 해준다. 예를 들면 debounce time 300ms 으로 지정하고 제출버튼을 빠르게 100번 클릭했다고 가정하자, 100번 클릭후 300ms 동안 더이상 이벤트 발생이 없을경우 1번 의 이벤트가 발생하도록 한다. 만약 100번 클릭후에 300ms 안에 또 다른 이벤트가 발생하게되면 debounce time 은 리셋이되고 앞의 방식대로 반복이되어진다.
const debounce = (callback, delay) =>{
let timerId;
// delay 가 경과하기 전에 이벤트가 발생하면 시간을 초기화하고 새로운 시간이 주어진다. 다시말해서 //delay 시간동안 여러 이벤트가 발생할 경우에는 callback 함수가 실행되지 않는다.
//event 는 timerId 를 기억하는 클로저를 반환한다.
return event =>{
if(timerId) clearTimeout(timerId);
timerId = setTimeout(callback, delay, event);
};
}
debounce는 주로 ajax 요청하는 자동 완성 구현 이나 버튼 중복 클릭을 방지 하기 위해서 사용되어진다. underscore의 debounce 함수나 lodash의 debounce 함수 사용을 권장한다고한다.
throttle은 짧은시간 간격으로 연속적으로 발생하는 이벤트들을 그룹화해서 일정 시간단위로 이벤트 핸들러가 호출되도록 호출 주기를 만든다. 좀 더 쉽게 말하자면, 일정시간동안 콜백함수를 실행시키지 않다가 지정한 시간 (delay) 이 되면 그때서야 콜백함수를 한번 실행하게 해준다. 예를 들자면 scroll event 가 있다. scroll event는 마우스가 움직일때마다 감지되어진다. 마우스 커스는 계속해서 움직여 scroll event가 연속적으로 발생되어진다. 성능면에서 얼마나 좋지 않을까? 시간을 400ms 로 지정했다고하면 400ms 전에는 마우스를 감지하지 않다가 400ms 가 지나면 그때서야 마우스 이벤트 핸들러 콜백함수가 실행이된다. 콜백함수가 실행이 되어지고나서 시간이 초기화가 되어진다.
const throttle = (callback,delay) =>{
let timerId;
return event =>{
//delay가 지나기 전까지는 아무 이벤트 (콜백함수) 가 실행되지 않다가 delay가 되어지면 콜백함수가 실행되어지고 시간이 초기화가 되어진다. 즉, delay 시간 간격마다 콜백함수가 한번씩 실행된다고 보면된다.
if(timerId) return;
timerId = setTimout(()=>{
callback(event);
timerId = null;
}, delay,event);
};
};
throttle 은 마우스 또는 스크롤을 감지하는 것들 예를들면 이미지 무한스크롤이나 scroll 이벤트 등에서
자주 사용되는 기술이다. Underscore의 throttle 함수나 Loash 의 throttle 함수를 자주 사용한다고 한다.