디바운싱과 쓰로틀링

Sming·2022년 5월 19일
0

디바운싱이란?

연속적으로 들어오는 입력중에 처음이나 마지막 입력만 실행하게 하는 기법을 디바운싱이라고 한다.

디바운싱의 종류

디바운싱도 어떤 시점을 입력하게 할건지에 따라서 trailing edge와 leading edge로 나눌수 있다.

debouncing trailing edge

연속적으로 들어오는 입력중에 마지막 입력만 실행하게 하는 기법이다.

  • window의 resize이벤트에서 마지막 변할때만 실행시키고 싶다면 사용한다.
  • input 입력할때마다 api 요청을 할때 사용한다.

debouncing leading edge

연속적으로 들어오는 입력중에 처음의 입력만 실행하게 하는 기법이다.

  • 제출을 누르는데 엔터로 꾹누르는 경우 처음의 요청만 보내고 뒤는 무시할수 있도록 하게 할때 사용한다.

디바운싱 코드

const $input = document.querySelector("#input");
const $app = document.querySelector("#app");

const callAjaxRequest = (e) => {
  $app.insertAdjacentHTML("beforeend", `<p>ajax 요청: ${e.target.value}</p>`);
};

const debounce = (func, wait, leading = false) => {
  let timer; // closure를 사용하여 timer 변수 초기화
  return (e) => {
    let callNow = leading && !timer; 

    const later = () => {
      timer = null;
      if (!leading) {
        func(e);
      }
    };

    clearTimeout(timer);
    timer = setTimeout(later, wait);

    if (callNow) {
      func(e);
    }
  };
};

$input.addEventListener("input", debounce(callAjaxRequest, 1000, true));

가장 처음에 closure를 이용하여 timer 변수를 선언합니다.

trailing edge case

먼저 leading이 false인 trailing edge상황부터 보겠습니다.

leading이 false이기에 callNow는 무조건 false가 됩니다.
첫 실행을 하면 먼저 clearTimeout은 timer가 없기때문에 넘어간후 setTimeout으로 laterwait시간 뒤에 실행시켜줍니다.

이 wait가 돌아가는 동안의 실행을 알아보겠습니다. 이상태에서는 다시 clearTimeout을 실행시켜 현재 타이머를 초기화시킵니다. 그런후 다시 타이머를 wait만큼 실행합니다. 그래서 이 wait시간이 지나서 later를 실행하기전까지 입력을 계속하면 계속 타이머가 취소되고 wait만큼 입력이 없다면 그때 later를 실행합니다.

leading edge case

이번엔 leading이 true인 leading edge에 대해서 알아보겠습니다.

leading이 true이기에 callNow는 timer에 따라서 false, true가 결정됩니다.
첫실행을 할 경우 timer는 할당되어있지않기에 undefined이고 leading이 true이기에 callNow는 true가 됩니다. 그리고 trailing edge와 동일하겍 타이머는 실행이 됩니다. 그런후 callNow가 true이기 때문에 등록한 함수를 바로 실행을 합니다.

그렇다면 그 다음 입력부터는 어떻게 될까요?
timer가 존재하기에 callNow가 false가 됩니다. 그런후 setTimeout을 꺼버리고 다시 timer를 재설정합니다. 이번에는 callNow가 false이기에 함수를 실행하지않습니다.

이것이 계속 반복되기에 timer가 돌아가는 동안은 모든 입력을 무시합니다. 그리고 wait만큼의 시간이 지나면 timer = null로 초기화하기때문에 다시 입력을 받을수 있는 상태가 됩니다.

쓰로틀링이란?

연속되는 입력에서 일정시간마다 한번만 입력될수 있도록 하는 프로그래밍 기법이다.

  • 스크롤 이벤트에 이벤트핸들러가 걸려있어서 너무 많은 횟수의 이벤트 핸들러를 불러올때

쓰로틀링 코드

const throttle = (func) => {
  let timer;

  return () => {
    if (!timer) {
      timer = setTimeout(() => {
        timer = null;
        func();
      }, 50);
    }
  };
};

$app.addEventListener("scroll", throttle(increaseCountNumber));

가장 처음에 closure를 이용하여 timer를 선언합니다. 첫 실행때 timer가 undefined이기에 if 문을 들어갑니다. 그런후 setTimeout을 실행합니다. 이 타이머는 50ms 후에 timer를 null로 초기화하고 함수를 실행합니다. 첫실행후 50ms동안은 timer가 존재하는 상태이기에 어떠한 입력도 무시합니다. 50ms후 함수를 실행하며 timer가 null이기에 다시 if문에 들어갈수있는 상태가 됩니다.

즉, 이런식으로 이용하면 50ms 마다 한번의 입력만 받게 하도록 하는 쓰로틀링의 코드가 완성됩니다.

디바운싱 vs 쓰로틀링

둘다 입력을 제한한다는 점에서 유사해 보이지만 차이점이 있다.

일단 디바운싱은 주로 api통신을 할때 사용된다. 여러번 똑같은 요청을 하면 쓸모없는 api 호출이 불러와지기 때문에 처음 한번 혹은 마지막 한번만 하게 한다.

반면 쓰로틀링은 성능최적화할때 사용된다. 스크롤 이벤트에 비용이 큰 이벤트 핸들러가 걸려있다고 생각해보자. 스크롤 이벤트는 살짝만 내려도 수십개의 이벤트가 발생하는것을 볼수있다. 이런곳에 비용이 큰 이벤트핸들러가 걸려있다면 당연히 성능에 문제가 생길수 밖에 없을것이다. 그래서 사용하는것이 쓰로틀링이다.

그래서 디바운싱은 입력을 마치기전까지 내가 계속 입력을 하고있다면 무한히 그 입력이 무시되고 쓰로틀링은 반드시 지정한 시간내에 한번은 실행하도록 보장을 해준다.

profile
딩구르르

0개의 댓글