Javascript - Debounce, throttle

김태수·2021년 8월 19일
0

기타

목록 보기
9/11

Event handling

브라우저에서 동작하는 scroll, resize, input, mousemove, ...
와 같은 이벤트들은 아주 짧은 시간 간격으로 연속하여 발생한다.
이러한 이벤트에 바인딩한 이벤트 핸들러는 과도하게 호출되어 성능에 문제를 일으키는 경우가 많다. Debouncethrottle은 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화 하여 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.

예를 들어, 아래와 같은 버튼을 짧은 시간 간격으로 연속해서 클릭했을 때 일반적인 이벤트 핸들러와 디바운스, 스로틀 된 이벤트 핸들러의 호출 빈도는 어떻게 다를까.

<!DOCTYPE html>
  <html>
  <body>
    <button>Click me</button>
    <pre>일반 클릭 이벤트 카운터 <span class='normal-msg'>0</span></pre>
    <pre>디바운스 클릭 이벤트 카운터 <span class='debounce-msg'>0</span></pre>
    <pre>스로틀 클릭 이벤트 카운터 <span class='throttle-msg'>0</span></pre>
    <script>
      const $button = document.querySelector('button');
      const $normalMsg = document.querySelector('button');
      const $debounceMsg = document.querySelector('button');
      const $throttleMsg = document.querySelector('button');

      const debounce = (callback, delay) => {
        let timerId;
        return event => {
          if (timerId) clearTimeout(timerId);
          timerId = setTimeout(callback, delay, event);
        };
      };

      const throttle = (callback, delay) => {
        let timerId;
        return event => {
          if (timerId) return;
          timerId = setTimeout(() => {
            callback(event);
            timerId = null;
          }, delay, event);
        };
      };

      $button.addEventListner('click', () => {
        $normalMsg.textContent = $normalMsg.textContent + 1;
      });
      $button.addEventListner('click', debounce(() => {
        $debounceMsg.textContent = $debounceMsg.textContent + 1;
      }, 500));
      $button.addEventListner('click', throttle(() => {
        $throttleMsg.textContent = $throttleMsg.textContent + 1;
      }, 500));
    </script>
  </body>
  </html>

/*         <20회 연속 클릭>
	일반 클릭 이벤트 카운터 20
    	디바운스 클릭 이벤트 카운터 1
        스로틀 클릭 이벤트 카운터 6
*/

디바운스와 스로틀은 이벤트를 처리할 때 매우 유용하며, 디바운스와 스로틀 구현에는 타이머 함수가 사용된다.

Debounce

디바운스는 짧은 시간 간격으로 이벤트가 연속해서 발생하면, 이벤트 핸들러를 호출하지 않다가 일정 시간이 경과한 이후에 이벤트 핸들러가 한번만 호출 되도록 한다. 즉, 디바운스는 짧은 시간 간격으로 발생하는 이벤트를 그룹화 하여, 이전 요청은 무시하고 마지막에 한번만 이벤트 핸들러가 호출되도록 한다


input이벤트로 사용자가 텍스트 입력 필드에 값을 입력할 때 마다 Ajax요청과 같은 무거운 처리를 수행한다면 사용자가 아직 입력을 완료하지 않았어도 요청이 여러번 전송될 것이다. 이는 서버에 부담을 주는 불필요한 처리이므로, 사용자가 입력을 완료했을 때 한 번만 Ajax 요청을 전송하는 것이 바람직하다.

Throttle

스로틀은 짧은 시간 간격으로 이벤트가 연속해서 발생하더라도 일정 시간 간격으로 이벤트 핸들러가 최대 한번만 호출되도록 한다. 즉 스로틀은 짧은시간 간격으로 연속해서 발생하는 이벤트를 그룹화하여 일정시간 단위로 이벤트 핸들러가 호출 되도록 호출 주기를 만든다.


예를들어, scroll이벤트를 이용할때, 사용자가 스크롤할 때 짧은 시간 간격으로 연속해서 발생한다. 이처럼 짧은 시간 간격으로 연속해서 발생하는 이벤트의 과도한 이벤트 핸들러의 호출을 방지하기 위해 스로틀은 일정한 주기를 만들어 해당 주기가 경과하기 이전에 이벤트가 발생하면 아무것도 하지 않다가, 해당 주기가 경과 했을 때 이벤트가 발생한다.
일정 시간 간격으로 이벤트 핸들러를 호출하는 스로틀은 scroll이벤트 처리나 무한 스크롤UI구현 등에 유용하게 사용된다.

Debounce, Throttle 구현

위의 예제와 같이 debounce와 throttle 함수를 직접 구현할 수 있으나,
실무에서는 더 정교하게 구현된 underscorelodash 의 debounce, throttle 함수를 사용하도록 하자.
Lodash를 사용하도록 하자

profile
개발학습 일기

0개의 댓글