All Articles

Throttling과 Debouncing

연이어 발생하는 이벤트에 의해 무의미한 리소스 낭비가 일어나지 않게끔 방지하는 기법들이다. 쓰로틀링은 특정 텀을 두고 주기적으로만 콜백함수를 실행하는 방법으로 scroll 이벤트에 많이 쓰이고, 디바운싱은 연이은 호출을 이른바 하나로 퉁치는 방법으로 ajax 통신에 많이 쓰인다.

선생님이 뭔가를 설명하고 학생의 질문을 받는 강의 상황에 비유하면 이렇게 볼 수 있겠다.

  • 선생님의 설명 : 이벤트 발생
  • 학생들의 질문 : 콜백함수 실행
  • “내가 강의를 하는 동안이더라도 질문이 생기면 언제든지 하렴” : 이벤트 발생 시마다 콜백함수가 실행되는 상황
  • “내가 일단 쭈욱 강의를 할테니, 30분 후에 반장이 대표로 질문하렴” : 쓰로틀링으로 효율화한 상황
  • “내가 일단 쭈욱 강의를 할테니, 강의가 다 끝나거든 반장이 대표로 질문하렴” : 디바운싱으로 효율화한 상황

Throttling

이벤트에 의한 콜백을 일정 시간 뒤에 호출 하는 것이다.
스크롤 이벤트는 생각보다 엄청나게 콜백을 중복 호출하게 된다. 스크롤 이벤트의 특성상, 매우 짧은 시간에 여러번 일어나므로 쓰로틀링을 적용하기에 적당하다. 예컨대 1초 등 특정 텀 안에 일어난 스크롤 이벤트는 단 1번만 콜백함수를 호출하게끔 만들면 효율적이 된다는 것이다.

원리는 이렇다.

  1. 이벤트가 발생하면, 특정 시간 후에 로직이 실행되도록 예약을 걸어둔다.
  2. 예약된 시간이 되기 전에 이벤트가 다시 발생하면, 새로운 예약을 걸지는 않고 그냥 스킵한다.

예시 코드

1초(1000ms)를 주기로 삼고 싶을 때의 예시다.

// 쓰로틀링
var timerForThrottle;
window.addEventListener('scroll', function(e) {
  if (!timerForThrottle) {
    timerForThrottle = setTimeout(function() {
      // 여기에 로직이 들어가면 된다.
      timerForThrottle = null;
    }, 1000);
  }
});

사이드 프로젝트를 하면서, 무한스크롤 방식 페이지네이션을 구현해야 할 일이 있어서 쓰로틀링을 적용해보았다. 제이쿼리 기반의 코드고, 따로 함수를 분리한 게 아니어서 가독성이 썩 좋진 않지만 참고하시라.
실제 프로젝트에 적용한 사례 >

Debouncing

연이어 호출되는 콜백 중 마지막 or 처음 것만 호출하도록 하는 것이다. 쓰로틀링과 약간 개념이 다르다. 쓰로틀링은 시간이라는 절대적 기준에 의해 효율화가 이루어지지만, 디바운싱은 연속성을 기준으로 효율화가 이루어진다. 예컨대 input tag(text type)에서 사용자가 작성하는 텍스트가 변화할 때 연관검색어를 보여주는 기능이 있다고 치자. 매 타이핑(자음, 모음 각각)에 대한 연관검색어가 유의미하지는 않을 것이다. 어느 정도 유의미한 단어가 만들어지면 사용자는 연속적인 타이핑을 멈출 것이고, 그렇게 연속성이 끊기는 순간, 단 1번만 ajax 요청을 하게끔 만들면 효율적이 된다는 것이다.

원리는 이렇다.

  1. 이벤트가 발생하면, 특정 시간 후에 로직이 실행되도록 예약을 걸어둔다.
  2. 예약된 시간이 되기 전에 이벤트가 다시 발생하면, 기존 예약을 취소하고 새로운 예약을 건다.

예시 코드

쓰로틀링과는 다르게, input에 대한 이벤트리스너를 예로 들었다. 연속성의 기준을 2초(2000ms)로 둔 예시다.

// 디바운싱
var timerForDebounce;
document.querySelector('#input').addEventListener('input', function(e) {
  if (timerForDebounce) {
    clearTimeout(timerForDebounce);
  }
  timerForDebounce = setTimeout(function() {
      // 여기에 로직이 들어가면 된다.
  }, 2000);
});

[참고자료]
https://webclub.tistory.com/607