쓰로틀링(Throttling)과 디바운싱(Debouncing)

상황

자바스크립트로 스크립트 작업을 하다보면 마주치는 상황이 있다.
연이어 다중 처리가 되어버리는 문제인데 그간 작업을 하면서 가장 많이 마주친 상황은 이렇다.

  1. 텍스트 필드에서 자동완성(keyup)을 하려고 하는데 타이핑을 할때마다 너무 자주 호출되는 상황
  2. onscroll 이벤트에 걸었는데 스크롤 단위마다 너무 자주 호출되는 상황
  3. 지도 이동이 완료되면 정보를 보여주고싶은데 이동중에도 계속 호출되는 상황

위와 같은 상황은 너무 자주 호출됨으로써 서버에 부담을 줄 수 있고 또 클라이언트에서도 다중 호출된 이벤트 때문에 성능에 문제가 생기는 경우가 많다.

간단히 쓰로틀링과 디바운싱을 설명하자면

진짜 간단하게 말하자면 이렇다

  • 디바운싱 : 많은 호출 중 마지막 것만 실행
  • 쓰로틀링 : 많은 호출을 일정 시간 간격으로 실행

쓰로틀링의 예

그렇다면 쓰로틀링은 언제 사용하면 되는가
위에 예를 들었던 부분 중에서 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() 함수를 이용해서 쉽게 사용할 수 있다.