새소식

Javascript

[JavaScript] debounce, throttle 개념 정리

  • -
반응형

 

오늘은 우테코를 진행하면서 배운 디바운스와 스로틀 개념에 대해서 정리해 보겠다.

이 정리는 우테코 수업과 모던 자바스크립트 딥 다이브 책을 읽고 정리해보았다. 

 

짧은 시간에 과도한 이벤트가 연속으로 발생한다면?

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

 

데이터 호출 버튼을 매우 빠르게 연속해서 눌러 생기는 성능 저하를 막고 싶다면?

사용자가 창 크기 조정을 멈출 때까지 기다려다가 resize event 를 해주고 싶다면?

입력창에 자동완성을 보여주고 싶은데 키보드 입력키 하나하나마다 해주고 싶지 않다면?

 

디바운스와 스로틀을 사용하여 불필요한 잦은 요청 제어와 일정 주기마다 원하는 동작을 제어하게 할 수 있다.

 

 

debounce

디바운스는 짧은 시간에 연속해서 발생한 이벤트를 그룹화해서 일정 시간이 경과된 이후에 한 번의 이벤트만 발생하게 하는 기술이다.

그래서 연속적으로 호출된 함수 중 마지막 함수 (혹은 제일 처음) 만 호출할 수 있게 한다.

 

 

 

이러한 디바운스 기술은 AJAX 검색에 자주 사용된다.

검색을 할 때 한글자, 한 글자 작성할 때마다 api 호출을 받아오게 되면 불필요한 요청이 너무 과도해질 수 있다.

 

만약 내가 그랜드 부다페스트 호텔 영화를 검색하고 싶은데 이를 치는 와중에 그랜드 피아노와 같은 검색 결과는 불필요한 비용이고, 또 이를 입력하면서 생기는 오타를 매번 요청하게 되면 효율적이지 않은 검색이 될 것이다.

 

만약 이 api 가 유료 api 라면 큰 손실이 날 수 도 있다.

 

그래서 보통 사람들은 타자를 연달아 치기 때문에 입력이 다 끝날 후에 요청을 보내는 것이 충분한 경우가 많다. 이를 때 디바운스를 사용해서 성능을 향상할 수 있다.

 

사용자가 입력을 완료했는지 여부는 정확히 알 수 없으므로 일정 시간 동안 입력 필드에 값이 입력되지 않으면 완료한 것으로 판단하고 이후에 요청을 부른 방식이다.

 

 

Debounce 작동 방식 

debounce 함수가 전달받은 딜레이 시간보다 짧은 간격으로 다시 이벤트가 발생되면 이전 타이머를 취소하고 새로운 타이머를 재설정한다. 따라서 딜레이 보다 짧은 간격으로 이벤트가 연속으로 발생하면 실행하고 싶은 콜백 함수를 호출하지 않다가 딜레이 시간이 모두 끝나면 그때 호출하는 방식이다.

 

 

예시 코드를 읽어보자

let debounce;
const $searchInput = document.querySelector("#input");
$searchInput.addEventListener("input", onSearchInputHandler);

const onSearchInputHandler = (e) => {
	
  if (debounce) {
    clearTimeout(debounce); 
	  // 딜레이 시간이 지나기 전에 이벤트가 발생하면 이전 타이머를 취소한다. 
  }
  debounce = setTimeout(() => {
    console.log("ajax 요청 부분", e.target.value);
  }, 3000);
};

 

 

실습 코드

예시 코드를 활용해서 아래 처럼 사용자의 입력값을 화면에 보이게 하는 코드를 작성해 보았다. 디바운스 되는 인풋 폼을 만들어서 사용자가 2초 동안 입력이 없다면 화면에 보이게 하는 코드이다.

 

Debounce Simple Mission

...

codepen.io

const regularInput = document.querySelector("#regular-input");

regularInput.addEventListener("input", () => {
  const regularSpan = document.querySelector(".rendered-text");
  regularSpan.textContent = regularInput.value;
});

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

const $debounceInput = document.querySelector("#debounced-input");
$debounceInput.addEventListener("input", () => {
  const debouncedSpan =  document.querySelector(".debounced-text");
  debounceFunc(() => {
    debouncedSpan.textContent = $debounceInput.value;
    // 실행될 콜백 함수 
  }, 2000);
});

 

 

 

throttle

 

스로틀은 짧은 시간 간격으로 이벤트가 발생하더라도 일정 시간 간격으로 이벤트 핸들러가 최대 한 번만 호출되게 한다. 즉, 일정 시간 단위로 이벤트 핸들러가 호출되도록 호출 주기를 만드는 것이다.

 

 

throttle 은 성능 문제로 스크롤 이벤트에 주로 사용된다. 스크롤을 올리거나 내릴 때 이벤트가 매우 많이 발생하여 과도한 호출로 안좋은 사용자 경험이 될 수 있다.

 

throttle 작동 방식

스로틀 함수는 딜레이 시간이 경과하기 이전에 이벤트가 발생하면 이를 무시하고 딜레이 시간이 경과했을 때 이벤트가 발생하면 콜백 함수를 호출하고 새로운 타이머를 재설정한다. 이 덕분에 딜레이 시간 간격으로 콜백 함수가 발생한다.

 

이 스로틀 함수는 scroll 이벤트 처리나 무한 스크롤 UI 구현에 유용하게 사용된다.

 

 

예시 코드를 읽어보자

let throttle;
const $searchInput = document.querySelector("#input");
$searchInput.addEventListener("input", onSearchInputHandler);

const onSearchInputHandler = (e) => {
  if (!throttle) { // 딜레이가 경과하지 않으면 무시 
    throttle = setTimeout(() => {
      throttle = null; // 딜레이가 경과되면 새로운 타이머 설정
      console.log("ajax 요청 부분", e.target.value);
      // 딜레이 간격으로 함수 호출 
    }, 300);
  }
};

 

 

 

실습 코드

스크롤 이벤트 콜백 함수가 실행될 때마다 count 1 증가시키기는 코드를 작성해보았다.

throttle를 적용하여 300ms 텀을 두고 실행하게 하여 일반적인 스크롤보다 요청 수를 조절해 보자

 

Debounce Example

...

codepen.io

const counter = document.querySelector("#counter");

let throttle;
const throttleFunc = (callback, delay) => {
  if (!throttle) {
    throttle = setTimeout(() => {
      throttle = null;
      callback();
    }, delay);
  }
}

window.addEventListener("scroll", () => {
  throttleFunc(() => {
    counter.textContent = Number(counter.textContent) + 1;
  }, 300);
});

const reset = document.querySelector(".reset");
reset.addEventListener("click", () => {
  counter.textContent = 0;
});

 

📘 정리

  • Debounce는 여러 번 발생하는 이벤트에서, 가장 마지막 또는 제일 처음 이벤트만을 실행하게 한다.
  • Throttle은 여러번 발생하는 이벤트를 일정 시간 동안, 한 번만 실행하게 한다.

 

 

 

반응형
Contents
-

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.