상황
자바스크립트로 스크립트 작업을 하다보면 마주치는 상황이 있다.
연이어 다중 처리가 되어버리는 문제인데 그간 작업을 하면서 가장 많이 마주친 상황은 이렇다.
- 텍스트 필드에서 자동완성(keyup)을 하려고 하는데 타이핑을 할때마다 너무 자주 호출되는 상황
- onscroll 이벤트에 걸었는데 스크롤 단위마다 너무 자주 호출되는 상황
- 지도 이동이 완료되면 정보를 보여주고싶은데 이동중에도 계속 호출되는 상황
위와 같은 상황은 너무 자주 호출됨으로써 서버에 부담을 줄 수 있고 또 클라이언트에서도 다중 호출된 이벤트 때문에 성능에 문제가 생기는 경우가 많다.
간단히 쓰로틀링과 디바운싱을 설명하자면
진짜 간단하게 말하자면 이렇다
- 디바운싱 : 많은 호출 중 마지막 것만 실행
- 쓰로틀링 : 많은 호출을 일정 시간 간격으로 실행
쓰로틀링의 예
그렇다면 쓰로틀링은 언제 사용하면 되는가
위에 예를 들었던 부분 중에서 onscroll 이벤트 같은것에 사용하는 편이다
onscroll이 계속해서 발생하고 있을 때 100ms 간격을 두고 함수를 실행하도록 제한을 둘 수가 있다
var throttleTimer;
$("#div").on('scroll', function(){
if(!throttleTimer){
throttleTimer = setTimeout(function(){
throttleTimer = null;
console.log('action')
},100))
}
});
위의 소스를 보면 id가 div라는 엘리먼트에서 스크롤 이벤트가 발생할때마다 작동하는데 throttleTimer가 null 일때만 100ms 뒤에 액션을 취하도록 되어있다.
setTimeout이 스로틀링의 핵심이다. 100ms 뒤에 실행되며 100ms 이전의 scroll이벤트에서는 무시되는 것
디바운싱의 예
디바운싱은 짧은시간동안 반복되는 이벤트가 있을 때 쓰로틀링과는 다르게 마지막 이벤트만 실행을 한다.
주로 ajax를 함께 이용하는 자동완성 같은 곳에 사용할 수 있다.
입력이 멈춘 후 100ms뒤에 마지막 한번만 실행하는 예
var debouncingTimer;
$("#textInput").on('keyup', function(){
if(debouncingTimer){
clearTimeout(debouncingTimer);
}
debouncingTimer = setTimeout(function(){
console.log('action');
},100);
});
위의 소스를 보면 id가 textInput이라는 텍스트 필드에서 keyup이벤트가 발생할때마다 호출되는데 debouncingTimer 가 null이 아닐경우 clearTimeout을 해서 실행을 중지시키게 된다.
그 아래쪽에서는 setTimeout으로 100ms 뒤에 실행되도록 되어있기 때문에 마지막 keyup 이벤트가 발생한 후 100ms 뒤에 action 이 실행되게 된다.
간단하지만 꼭 필요함
쓰로틀링과 디바운싱은 굉장히 간단한 개념이지만 실제로 개발을 하면서 꼭 필요한 부분이다.
위의 소스에서는 별도로 타이머를 clear하는 부분과 set하는 부분으로 직접 작성했지만.
더욱 쉽게 사용하려면 lodash 라이브러리 같은 것을 사용하면 _.throttle() 이나 _.debounce() 함수를 이용해서 쉽게 사용할 수 있다.