디바운스는 동일한 이벤트가 연달아 발생할 때 마지막 이벤트를 감지해 처리하는 이벤트 처리 방식이에요.
마지막 이벤트가 발생하고 개발자가 지정한 시간 이후에 Callback을 실행합니다.

디바운스를 구현하는 방법은 이벤트가 발생할 때마다 새로운 타이머를 설정해주면 돼요.
그러다 어느 순간부터 이벤트가 발생하지 않으면 새로운 타이머를 설정하지 않을 거에요.
그럼 마지막 이벤트가 설정한 타이머에 의해 Callback을 실행하게 됩니다.

저는 resize 이벤트를 핸들링하는 로직, 사용자 입력에 실시간으로 반응할 필요가 없는 동작을 구현할 때 디바운스를 종종 사용해요.
예를 들어 <input /> 입력 필드에 사용자가 입력한 값이 validation 조건에 맞지 않는 경우 힌트 메시지를 보여줘야 한다고 해볼께요.
만약 사용자가 아직 입력 중이라면 힌트 메시지를 바로 보여주지 않아도 괜찮습니다.
이런 경우 디바운스로 핸들링 로직을 감싸 lazy하게 반응하도록 의도할 수 있어요.

let debounceTimeoutId: NodeJS.Timeout;

// 이벤트가 발생할 때 실행할 함수
function handleEventDebounce(ms: number) {
  clearDebounceTimeout();
  debounceTimeoutId = setTimeout(() => {
    // 이벤트에 반응하는 로직

    clearDebounceTimeout(); // 목적을 다 한 타이머까지 clear
  }, ms);
}

function clearDebounceTimeout() {
  if (debounceTimeoutId === undefined) return;

  clearTimeout(debounceTimeoutId);
  debounceTimeoutId = undefined;
}

비교: Throttle

쓰로틀은 디바운스와 반대로 첫 번째 이벤트를 감지하는 이벤트 처리 방식이에요.

디바운스보다 더 쉽게 구현할 수 있어요.
첫 번째 이벤트가 발생했을 때 타이머를 설정하고 다음 이벤트가 발생했을 때 타이머가 유효하다면 이벤트를 무시하면 됩니다.

참고: Lodash

직접 구현하지 않아도 많이 사용되고 있는 Lodash 라이브러리에서 편하게 가져다 쓸 수 있어요.

Lodash 공식 문서 링크