[JS] 디바운스와 스로틀

Urther·2021년 12월 28일
0

JavaScript

목록 보기
4/8

문제 발생 ⛑

100px 정도 스크롤을 이동했을 때 top 버튼이 생기게끔 하고 싶었다.
그렇다면 현재 스크롤의 위치를 아는 함수를 사용해주어야 했다.

scrollY()pageYOffset()의 선택지가 존재했다.

브라우저 호환성을 생각했을 때, scrollY() 보단 pageYOffset() 를 쓰는 것이 더 좋다.

Internet Explorer 9 미만의 구형 환경에서는 두 개의 속성 모두 적용이 되지 않는다. 만약 Internet Explorer 9 미만의 구형 환경을 고려해야 한다면 다른 방법을 생각해야 한다.

window.addEventListener('scroll', 이벤트 발생시 작동할 메서드);

window.pageYOffset 속성을 사용하여 어떻게든 현재 스크롤 된 위치는 알 수 있게 되었지만, 아래와 같이 짧은 시간 간격으로 같은 이벤트(스크롤 되었을 때 실행되는) 가 과도하게 호출되는 문제점이 생긴다.

과도하게 이벤트를 호출 할 경우, 성능에 문제를 일으킬 수 있다.

문제 해결 방안 🗣

짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화 해서 과도한 이벤트 핸들러의 호출 방지하는 기법이 필요하다 !

디바운스

연속해서 발생하는 이벤트에 호출하지 않다가 일정 시간이 경과한 이후에 이벤트 핸들러가 한번만 호출되도록 한다.

짧은 시간 간격으로 이벤트가 연속해서 발생하면 이벤트 핸들러를 호출하지 않다가 일정 시간 동안 이벤트가 더 이상 발생하지 않으면 이벤트 핸들러가 한 번만 호출되도록 하는 디바운스는 resize 처리나, input 요소에 입력된 값으로 ajax 요청하는 입력 필드 자동완성 UI 구현, 버튼 중복 클릭 방지 처리 등에 유용하게 사용된다.

const debounce = (callback,delay) => {
  let timerId;
  return event=>{
    if(timerId) clearTimeout(timerId);
    // 만약, 시간이 지나서 (delay) 발생한 event가 아니라면, clearTimeout으로 타이머를 취소해준다.
    timerId=setTimeout(callback, delay, event);
    // 마지막에 발생한 이벤트만 setTimeout을 통해 이벤트를 걸어준다.
  };
};

👩‍💻 코드 설명

delay보다 짧은 간격으로 이벤트가 발생하면 callback 이 호출되지 않는다. | delay가 경과하기 이전에 이벤트가 발생하면 이전 타이머를 취소하고 새로운 타이머를 재설정한다.

스로틀

짧은 시간 간격으로 이벤트가 연속해서 발생하더라도 일정 시간 간격으로 이벤트 핸들러가 최대 한 번만 호출되도록 한다.

즉, ⏤ 디바운스는 마지막(또는 처음)의 함수를 호출하지만,⏤ 스로틀 함수는 호출 주기를 만든다.

위와 같은 스크롤같은 문제는 호출 주기를 만들어서 스크롤 위치를 계산하는 함수를 호출하면 되기 때문에 스로틀을 이용하는 것이 좋다. ⏤ 디바운스가 무한 스크롤에 적합하지 않은 이유는 스크롤에서 잠깐 멈춘 사이에 마지막에 발생한 event를 실행시키기 때문에 적합하지 않음

const throttle = (callback, delay) => {
  let timeId;
  return event=>{
    if(timerId) return;
    timerId = setTimeout(()=>{
      callback(event);
      timerId=null;
    },delay,event);
  };
}

👩‍💻 코드 설명

delay 간격으로 callback 을 호출한다. | delay 가 경과하기 이전에 이벤트가 발생하면 아무것도 안하다가 delay가 경과했을 때 이벤트가 발생하면 새로운 타이머를 재설정한다.


실무에서는 Underscore의 throttle,debounce 함수나, Lodash throttle , debounce 함수를 사용하는 것이 좋다. 👌🏻


Reference |
MDN - pageYOffset()
MDN - ScrollTo()
모던자바스크립트

profile
이전해요 ☘️ https://mei-zy.tistory.com

0개의 댓글