Debounce와 Throttle

창건·2023년 6월 14일
0

scroll, resize, input, mousemove와 같은 이벤트는 짧은 시간 간격으로 연속해서 발생합니다.

이런한 이벤트에 바인딩된 이벤트 핸들러는 과도하게 호출되어 성능에 문제를 일으킬 수 있습니다.

Debounce와 Throttle은 짧은 시간 동안 연속해서 호출되는 이벤트 핸들러를 그룹화하여 과도한 호출을 방지하는 기법입니다.

Debounce

짧은 시간 간격으로 이벤트가 연속해서 발생하면 이벤트 핸들러를 호출하지 않다가 일정 시간이 경과한 이후에 이벤트 핸들러가 한 번만 호출되도록 하는 것

  • input 이벤트는 사용자가 텍스트 입력 필드에 값을 입력할 때마다 연속해서 발생합니다.
  • 만약 사용자가 입력할 때마다 Ajax 요청과 같은 무거운 작업을 한다면 큰 부담이 될 것입니다.
  • 따라서 사용자가 입력을 완료했을 때 한 번만 Ajax 요청을 전송하는 것이 좋을 것입니다.

구현

핵심이 되는 debounce를 다시 한번 보겠습니다.


const debounce = (callback, delay) => {
  let timerId;
  return event => {
    if (timerId) clearTimeout(timerId);
    timerId = setTimeout(callback, delay, event);
  }
};
  • timerId가 존재하면, 즉 이미 함수가 호출된 상태라면 clearTimeout을 통해 이전 호출을 취소합니다.

  • 만약 timerId가 존재하지 않는다면, 즉 함수가 호출된적이 없다면, setTimeout을 통해 최초로 호출하게 됩니다.

  • 눈치채셨겠지만, Debounce와 Throttle을 구현하는 데에 가장 중요한 개념은 클로저입니다.
    debounce는 호출되었을 때 중첩함수를 반환하는데, 이 중첩함수는 상위 스코프인 debounce에서 선언된 timerId를 참조할 수 있습니다.

Throttle

짧은 시간 간격으로 이벤트가 연속으로 발생하더라도 일정 시간 간격으로 이벤트 핸들러가 최대 한번만 호출되도록 하는 것

  • scroll 이벤트가 발생했을 때, 이전에 호출된 이벤트 핸들러가 처리되지 않았다면 이벤트 핸들러를 새로 등록하지 않는다.
  • 이벤트 핸들러는 일정 시간을 주기로 호출된다.

구현

const throttle = (callback, delay) => {
  let timerId;
  return event => {
    if (timerId) return;
    timerId = setTimeout(() => {
      callback(event);
      timerId = null;
    }, delay);
  }
  • debounce와 마찬가지로 클로저를 이용하여 구현했습니다.
  • debounce와 차이점은, 이전에 호출된 이벤트 핸들러의 호출을 취소하느냐에 있습니다.
  • debounce는 이전 이벤트 핸들러 호출을 취소하고 새로 등록하지만, throttle은 새로 이벤트 핸들러를 등록하지 않습니다.

참고

Leetcode에서 debounce, throttle 구현을 연습해 볼 수 있습니다.
다른 자바스크립트 개념에 대해서도 문제를 풀며 연습할 수 있습니다👍

profile
피곤한만큼 성장할 수 있으면

0개의 댓글