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

이번 미션에서 검색어 자동완성 기능이 있었는데 500ms 동안 새로운 입력이 없어야 이벤트가 발생하도록 하는 조건이 있었다.

처음에 sleep 함수를 만들어 단순히 500ms가 지난 후에 이벤트 핸들러가 실행되도록 구현했었다.

cosnt sleep = (ms) => {
    return new Promise(r => setTimeout(r, ms));
  }

sleep 후 실행되는 핸들러는 서버에 자동 완성된 단어들의 리스트를 받아오는 요청을 하는 fetch가 실행되도록 했는데 구현하다 보니 먼저 요청한 데이터가 나중에 요청한 데이터보다 늦게 도착하는 문제가 있었다.

(gif로 변환하니 느리네...)

이 부분을 스크럼 시간에 공유했더니 다른 분이 타이머를 클리어하는 방법으로 하셨다 해서 나도 그 방법을 사용하려다 예전 코코아 때 디바운싱과 쓰로틀링을 들어본 기억이 있어 다시 찾아봤다.

디바운싱

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

이번 미션을 예로 들자면 입력 이벤트가 발생하고 500ms가 지나기 전에 입력 이벤트가 또 발생하면 이전의 타이머가 클리어 되고 새로 발생한 이벤트 타이머가 세팅되는 것이다. 즉 타이머를 계속 갱신하는 것이다.

쓰로틀링

마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것

쉽게 말해 500ms마다 이벤트가 한 번만 발생하게 하는 것이다.

적용

현재 내 상황에서 필요한 기능은 이전에 발생한 이벤트가 fetch 요청을 하지 않고 더 늦게 발생한 이벤트가 실행되는 것이었기 때문에 디바운싱이 필요하다고 판단했다.

  const debounce = (f, ms) => {
    let timer = null;

    return (...args) => {
      clearTimeout(timer);
      return new Promise(r => {
        timer = setTimeout(() => r(f(...args)), ms);
      });
    };
  }

확실히 디바운싱을 했더니 이벤트 발생 횟수가 줄었다. 처음엔 이대로 문제가 해결된 줄 알았다. 하지만 문제는 해결되지 않았다. 이벤트 발생 횟수가 줄면서 내가 체감하는 오류 발생 횟수가 줄었을 뿐이었다. 사실 위에 첨부한 gif는 디바운싱을 적용하고 나서 동작하는 모습이다.

이 문제는 다음 네트워크 요청 취소에서 해결이 된다.

좋은 웹페이지 즐겨찾기