스로틀링과 디바운스

camel·2023년 7월 21일
1
post-thumbnail

이번에 스크롤 이벤트를 컨트롤할 일이 생겼다.
그래서 그것을 디바운스로 처리하려고 했는데,
스크롤은 디바운스로 처리하기가 좀 애매했다.

그래서 오늘 느낀 디바운스와 스로틀링의 차이점에 대해 적고
실제 적용한 것을 예시로 들며 얘기해보겠다.




이벤트를 적절하게 제어하거나 최적화하는 방법을 사용하는데,
이 중 대표적인 것이 스로틀링(Throttling) 또는 디바운싱(Debouncing)을 적용하는 것이다.

스로틀링(Throttling)

일정한 시간 간격(예: 100ms)으로 스크롤 이벤트를 처리합니다. 스로틀링은 일정 시간 동안 이벤트가 발생하면 처음 한 번만 이벤트를 실행하고, 그 후 일정 시간이 지난 후에 다시 이벤트를 실행합니다. 이를 통해 스크롤 이벤트가 빈번하게 발생할 때 이벤트 핸들러의 실행을 제어할 수 있습니다.

디바운싱(Debouncing)

일정 시간(예: 100ms)이 지난 후에 스크롤 이벤트를 처리합니다. 디바운싱은 일정 시간 동안 이벤트가 발생하면 타이머를 시작하고, 일정 시간이 지난 후에 타이머가 만료되면 이벤트를 실행합니다. 만약 이벤트가 중간에 새로 발생하면 타이머를 초기화하여 다시 일정 시간을 기다립니다. 이를 통해 스크롤 이벤트가 연속적으로 발생할 때 마지막 이벤트만 실행되도록 할 수 있습니다.

스로틀링과 디바운싱은 setTimeout과 clearTimeout 함수를 사용하여 구현할 수 있다.
외부 라이브러리인 Lodash나 Underscore.js에서 제공하는 throttle 또는 debounce 함수를 사용하여 간편하게 적용할 수도 있지만, 직접 구현하는 것을 선호하였다.

스로틀링 코드와 예시

let isScrolling = false;

function handleScrollThrottled(event) {
  if (!isScrolling) {
    isScrolling = true;
    // 이벤트 시작
    // ...

    // 일정 시간(예: 100ms) 후에 isScrolling을 false로 변경하여 다음 이벤트가 실행되도록 함
    setTimeout(() => {
      isScrolling = false;//이벤트 끝
    }, 100);
  }
}

let을 사용하였는데, react에서 let은 지양한다.
그래서 react에서 사용한다면 useRef를 사용하는 것이 좋다.
(react의 의도와 더 잘맞는다)

쓰로틀링은 어떠한 상황에서 쓰는게 좋냐면,
처음 이벤트가 발생하고나서 이후에 이벤트를 막을 때 사용하는 것이 좋다.
예를 들어서 스크롤을 내릴 때, 이벤트가 여러번 발생하는데 위와 같이 적용해주면
처음 실행이 끝난 후에야 이벤트가 작성하기 때문에 이벤트를 제어하기 편리하다.
(실행 시간을 위에서는 0.1초 100으로 잡았다.)

그래서 내가 이벤트가 발생하는 동안 연속으로 발생하지 않았으면 좋겠다 할때 사용하는 것이 좋다.
즉 쓰로틀링에서는 처음 이후에 이벤트를 발생 안시켰으면 좋겠다~ 할때 사용하는 것이 적절하다.

디바운싱(Debouncing) 코드

let timerId;

function handleScrollDebounced(event) {
  // 이전에 설정된 타이머가 있으면 취소하여 초기화
  if (timerId) {
    clearTimeout(timerId);
  }

  // 일정 시간(예: 100ms) 후에 스크롤 이벤트를 처리하는 타이머 설정
  timerId = setTimeout(() => {
    // 이벤트 처리 로직
    // ...

    // 타이머 초기화
    timerId = null;
  }, 100);
}

이것도 마찬가지로

let을 사용하였는데, react에서 let은 지양한다.
그래서 react에서 사용한다면 useRef를 사용하는 것이 좋다.
(react의 의도와 더 잘맞는다)

디바운스는 어떠한 상황에서 쓰는게 좋냐면,
마지막 이벤트가 실행되었으면 좋겠다. 라는 생각이 든다면 사용하는 것이 좋다.
예를 들어서 이벤트에 맞추어서 api 요청을 한다면 매번 움직일 때마다 api 요청을 하는 것이 아니라 마지막 이벤트에만 맞추어서 api 요청을 했으면 좋겠다 할때 사용하는 것이 좋다.

쓰로틀링과 비교했을 때, 쓰로틀링은 처음 이후에 이벤트를 통제한다면,
(쓰로틀링 처음 이벤트 이후에 통제하고 일정 시간이 지나면 끝나는 이벤트가 작동한다)
디바운스는 마지막 이벤트만 발생했으면 좋겠다 할때 사용하는 것이 적절하다.




끝으로

처음에는 이 둘의 차이점이 뭔지 언제 사용해야하는지 잘몰랐는데,
조금씩 구현하고 사용해보면서 이해도가 생겼다.
그리고 처음 구현하였을 때는 let을 사용하였는데
useRef를 사용하여서 스코프(react const 지향)에 대한 문제를 극복하였고,

react 의도와 맞게 사용했다는 점에서 만족스러웠다.

profile
화이팅~ 가보자구

4개의 댓글

comment-user-thumbnail
2023년 7월 21일

좋은 글 잘 읽었습니다, 감사합니다.

답글 달기
comment-user-thumbnail
2023년 7월 21일

정리를 잘 해주셔서 한번에 이해가 잘 된 것 같아요!잘 보고 갑니당

답글 달기
comment-user-thumbnail
2023년 7월 23일

검색엔 디바운스를 많이 쓴다고만 알고있었는데 이런 차이가 있었네요 잘 보고 갑니다 !

답글 달기
comment-user-thumbnail
2023년 7월 23일

직접 구현해보는거 좋네요!! 잘 읽고 갑니당

답글 달기