[JavaScript] 디바운싱과 쓰로틀링

D uuu·2024년 1월 1일
0

JavaScript

목록 보기
8/8

언제 사용할까?

디바운싱과 쓰로틀링은 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법입니다.

결제하기 버튼을 누르면 결제가 되는 페이지가 있다고 합시다. 만약 사용자가 결제하기 버튼을 따닥하고 더블 클릭하면 어떻게 될까요? 결제 하는 API 요청이 두번 나가게 되고 결제가 두번 이뤄질지도 모릅니다.

네이버 검색창에 주소를 검색할때 엔터를 치지도 않았는데 결과가 바로바로 나오는 걸 확인 할 수 있습니다. 아마도 입력창에 이벤트 함수를 설정해놓고 입력값이 들어오면 API 요청이 나가도록 설정해놨을지도 모릅니다.

만약 서울특별시 종로구 인사동··· 을 입력할때마다 API 콜이 나간다면 ㅅ,ㅓ성,서우,서욽,서울특 와 같이 너무 많은 API 콜이 나가게 됩니다. 거기에다가 "서우" 과 같은 의미 없는 단어임에도 불구하고 API 콜이 나가는건 너무 낭비라는 생각이 듭니다.

생각해보면 애플리케이션을 사용하면서 위와 같은 상황이 생각보다 많습니다. 그래서 디바운싱과 쓰로틀링에 대해서 알고 있으면 여러 상황에서 적절하게 사용할 수 있습니다.

디바운싱

디바운싱은 짧은 시간 간격으로 이벤트가 연속으로 발생하면 이벤트 핸들러를 호출하지 않다가 일정 시간이 경과한 이후에 이벤트 핸들러가 한번만 호출되도록 합니다. 즉, 마지막에 한번만 이벤트 핸들러가 호출 됩니다.

디바운싱은 어디에 사용할까?

  • 검색 입력 : 사용자가 검색창에 연속적으로 입력을 하면 매번 검색 요청을 보내는 것은 비효율적이므로 디바운싱을 적용하여 일정 시간 동안 입력이 없을때에만 요청을 보내는 방법을 사용한다.

  • 더블 클릭 방지 : 버튼 클릭 이벤트를 처리할때 디바운싱을 적용하면, 사용자가 연속적으로 버튼을 클릭할 경우 마지막에 클릭한 것만 이벤트 처리 되도록 적용하여 중복 실행이나 오작동을 방지할 수 있다.

  • 유료 API 사용 : 구글 맵과 같이 유료 API 를 사용할 경우, API 콜 하나하나가 다 돈이므로 디바운싱으로 연속적인 요청을 제어하면 API 사용량을 관리할 수 있고 비용도 절감할 수 있다.



쓰로틀링

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

쓰로틀링은 보통 성능 문제 때문에 많이 사용합니다. 특징 자체가 실행 횟수에 제한을 거는 것이기 때문에 너무 많이 발생하는 이벤트의 횟수에 제한을 걸어 성능 이슈를 피하고자 주로 사용합니다.

쓰로틀링은 어디에 사용할까?

  • 스크롤 이벤트 : 스크롤을 올리거나 내릴때 스크롤 이벤트를 설정해뒀다면, 매우 빈번하게 실행되기 때문에 성능에 문제가 생길 수 있다. 따라서 쓰로틀링을 적용시켜서 이벤트가 발생되는 주기를 설정할 수 있다.

  • 더블 클릭 방지 : 디바운싱과 마찬가지로 버튼 클릭 이벤트를 처리할때 쓰로틀링을 적용할 수 있다. 사용자가 연속적으로 버튼을 클릭할 경우 일정 시간 동안 이벤트 발생을 제한을 둠으로써 중복 실행을 방지할 수 있다.

  • 실시간 업데이트 : 실시간으로 데이터를 받아오는 경우, 쓰로틀링을 적용하면 데이터를 받아오는 속도를 제한할 수 있어 서버에 걸리는 부하를 조절하거나 API 요청의 속도를 제한할 수 있다.



<디바운싱과 쓰로틀링을 적용한 버튼 예제>

const clickBtn = document.querySelector("button");
const clickCnt = document.getElementById("clickCount");
const debounceCnt = document.getElementById("debounceCount");
const throttlingCnt = document.getElementById("throttlingCount");

let debouncingId;
let throttlingId;

clickBtn.innerHTML = "클릭!";

function debouncing(func, timeout = 1000) {
  clearTimeout(debouncingId);
  debouncingId = setTimeout(func, timeout);
}

function delayFunction() {
  debounceCnt.innerHTML = parseInt(debounceCnt.innerHTML) + 1;
}

function throttling(func, timeout = 1000) {
  if (throttlingId) return;

  throttlingId = setTimeout(() => {
    func();
    throttlingId = undefined;
  }, timeout);
}

function delayFunction2() {
  throttlingCnt.innerHTML = parseInt(throttlingCnt.innerHTML) + 1;
}

clickBtn.addEventListener("click", () => {
  clickCnt.innerHTML = parseInt(clickCnt.innerHTML) + 1;
  debouncing(delayFunction);
  throttling(delayFunction2);
});


<디바운싱을 적용해 검색창 구현>

let timer;
document.querySelector("input").addEventListener("input", function (e) {
   if (timer) {
    clearTimeout(timer);
  }
  timer = setTimeout(function () {
    console.log("API 요청", e.target.value);
  }, 300);
});

❗디바운싱을 적용하지 않은 경우

❗❗디바운싱을 적용한 경우



마무리

위에서 구현한 디바운싱 과 쓰로틀링은 간략하게 구현하여 완전하지 못하다. 찾아보니 Underscore, lodash 라는 라이브러리를 많이 사용하는 것 같다. npm trend 에서 찾아보니 lodash 가 훨씬 높은 다운로드수를 보유하고 있다. 실무에서 디바운싱, 쓰로틀링을 구현해야 한다면 라이브러리를 사용하는 것을 고려해봐도 좋을 것 같다.





도움 받은 곳

https://www.zerocho.com/category/JavaScript/post/59a8e9cb15ac0000182794fa
https://velog.io/@cyd5538/%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81%EA%B3%BC-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글