ITstudy

프론트엔드 꼭 필요한 디바운싱과 쓰로틀링 중요 개념

martinooo 2024. 1. 3. 17:18
728x170

 

디바운스와 쓰로틀링 모두 웹에서 발생하는 이벤트를 제어하는 방법이다.

 

예를 들어 스크롤 이벤트의 경우 스크롤링 할 때마다 발생하는데, 그 때마다 같은 작업을 실행하게 되면 성능 문제가 발생할 수 있다. 디바운스와 쓰로틀링을 적절한 상황에서 사용하여 그런 상황이 발생하지 않도록 막을 수 있다!

목록으로가기 or 버튼 이벤트에서 여러번 클릭하면 여러번에 이벤트가 일어나면서 예측할 수 없는 다음 액션이 일어날수도 있다.

ex: 목록으로가기 이벤트가 router.back()을 2번 누르면 history 2번째 stack 페이지로 이동하는 경우도 있다.  

디바운싱과 쓰로틀링은 성능을 목적으로 자바스크립트의 이벤트를 제어하기 위해 사용되는 기법이다.

 

디바운싱 (Debouncing)

연속으로 호출되는 함수들 중에 마지막에 호출되는 함수(또는 제일 처음 함수)만 실행되도록 하는 것

 

 

자바스크립트에서의 디바운싱은 마지막으로 발생한 이벤트를 기준으로 특정 time이 지난 후 하나의 이벤트만 실행되도록 한다.

디바운싱을 적용하면 좋은 예시로는 검색 기능의 키 이벤트(input)가 있다.

검색 버튼을 누르지 않아도 사용자가 입력한 값이 변경될 때마다 자동으로 검색 요청을 보내는 기능을 만든다고 한다면, 사용자가 검색어를 다 입력하지 않았을 때에도 요청이 보내지게 되므로 비효율적이다.

이러한 경우에 디바운싱을 적용하면 사용자의 입력이 끝나고 일정 시간이 지난 후에 검색 요청이 1번만 보내지므로 성능을 향상시킬 수 있다.

 

디바운싱을 코드로 표현하면 다음과 같다.

const inputElement = document.querySelector('#ID값');
const DELAY = 500;
const handleChange = () => {
  console.log('요청!');
}

let timer;

inputElement.addEventListener('input', () => {
  if (timer) clearTimeout(timer);
  timer = setTimeout(handleChange, DELAY);
});

 

 

디바운싱을 구현하기 위해서는 setTimeout 함수와time(기준 시간)이 필요하다.

이벤트가 발생할 때마다 timer 변수에 콜백 함수를 반환하는 setTimeout 함수를 값으로 할당한다.

time 이내에 새로운 이벤트가 발생할 때마다 타이머를 초기화 해준다고 이해하면 된다.

time 이내에 새로운 이벤트가 발생한다면 clearTimeout을 해줌으로써 콜백 함수는 실행되지 않으며, 발생하지 않으면 setTimeout은 콜백 함수를 실행하게 된다.

리액트에서는 다음과 같이 함수 실행에 디바운싱을 적용한 커스텀 훅을 만들어 사용할 수도 있다.

 

import { useCallback, useEffect } from 'react';

const useDebounceFunc = (func: () => void, delay: number, deps: any[]) => {
  const callback = useCallback(func, deps);

  useEffect(() => {
    const timer = setTimeout(() => callback(), delay);
    return () => clearTimeout(timer);
  }, [callback, delay]);
};

export default useDebounceFunc;

 


쓰로틀링(throttling)

 

자바스크립트에서의 쓰로틀링은 짧은 시간 내에 과도한 이벤트 실행으로 인해 발생하는 성능 저하를 막기 위해 일정한 time slice를 주기로 이벤트가 한 번만 실행되도록 제한한다.

예를 들어 1초에 100번의 업데이트가 일어나는 DOM 요소에 이벤트 핸들러를 추가한다면, 이벤트는 1초에 100번이나 실행되므로 성능에 무리를 줄 수 있다.

쓰로틀링을 적용하게 되면 불필요한 이벤트 실행 횟수를 줄일 수 있어 성능을 향상시킬 수 있다.

쓰로틀링을 적용하면 좋은 예시로는 scroll, resize, drag, mouse 이벤트, 애니메이션 등이 있다.

예를 들어 스크롤 이벤트의 경우, 크롬 기준 2px 단위로 이벤트가 발생하게 된다.

사용자가 1초에 1000px의 스크롤을 하게 되는 경우에는 약 500번의 이벤트가 발생되므로 성능에 좋지 않을 수 있다.

이러한 경우에 time = 100 간격으로 이벤트가 실행되도록 쓰로틀링을 적용하면 실행 횟수를 10번으로 줄일 수 있다.

 

쓰로틀링을 코드로 표현하면 다음과 같다.

const DELAY = 500;
const handleScroll = () => {
  timer = null;
  console.log('스크롤!');
}
        
let timer;  
   
window.addEventListener('scroll', () => {
  if (!timer) timer = setTimeout(handleScroll, DELAY);
});

 

 

lodash를 사용한 debounce, throttle 적용

lodash에서는 위에서 설명한 디바운싱과 쓰로틀링을 쉽게 적용할 수 있도록 debounce, throttle 메소드를 제공한다.

아래와 같이 디바운싱 혹은 쓰로틀링을 적용할 함수를 메소드로 감싸고 2번째 인자로 delay 값을 전달하면 된다.

lodash를 활용해서 더 간편하게 디바운싱과 쓰로틀링을 사용할 수 있다.

 

- 디바운싱 예제

import { debounce } from 'lodash';

const DebounceInput = () => {
  const handleChange = debounce(({ target }) => {
    console.log('debounce', target.value);
  }, 500);

  return <input type="text" onChange={handleChange} />;
};

export default DebounceInput;

 

- 쓰로틀링 예제

import { throttle } from 'lodash';

const ThrottleInput = () => {
  const handleChange = throttle(({ target }) => {
    console.log('throttle', target.value);
  }, 500);

  return <input type="text" onChange={handleChange} />;
};

export default ThrottleInput;

 


 

웹에서 바로 사용할 수 있는 이미지 변환, SEO 태그, 글자수 계산기 등 웹툴을 제공합니다.

 

그리드형