스크롤 이벤트 디바운싱

렐루·2024년 4월 30일
0

쓰로틀링 디바운싱

간략한 예시

아이디 중복 확인 기능을 예시로 들어보겠습니다.
원하는 아이디 입력을 완료한 후 마지막에 한번만 확인 버튼을 클릭해서 중복확인을 받는 방법이 있고,
사용자가 별도의 확인버튼 없이 아이디를 입력 하기만 해도 자동으로 중복확인이 되는 방법이 있습니다.

후자의 경우, 사용자의 입력이 계속되는 동안 change 이벤트가 계속해서 발생하며 콜백함수로 중복확인을 계속해서 받을 수 있습니다.
다만 이렇게 작동하면 불필요하게 많은 요청을 하게 되고 성능적으로나 비용적으로나 불리한 상황이 생기게 됩니다.

위와 같은 불필요한 통신을 줄이는 방법으로 디바운싱과 쓰로틀링을 사용할 수 있습니다.

나의 상황, 코드

window.addEventListener("scroll", function () {
  const nav = document.getElementById("top_nav");
  const content = document.getElementById("nav_container");
  const contentRect = content.getBoundingClientRect();

  if (contentRect.top < window.innerHeight && contentRect.bottom > 0) {
    // content가 화면 안에 있을 때
    nav.style.visibility = "hidden"; // nav를 화면 상단에 고정
    nav.style.zIndex = "-1";
  } else {
    // content가 화면 밖으로 나갔을 때
    nav.style.visibility = "visible"; // nav를 화면 위로 사라지게 함
    nav.style.zIndex = "10";
  }
});

위는 제가 과제를 하면서 작성한 코드입니다.
상단의 nav 바가 화면에 따라 등장하게 하는 코드입니다.
메인 nav바가 스크롤하여 안보이게 되면 보조 nav바를 상단에 고정하는 간단한 화면입니다.

불필요한 이벤트를 줄이라는 피드백을 받아 수정하게 되었습니다.

선택, 디바운싱

쓰로틀링은 주로 성능의 문제가 발생할 때 사용한다고 합니다.
그도 그럴것이 쓰로틀링은 시간 락을 걸어서 함수가 실행하고 정한 시간만큼 입력을 제한하는 것인데 그 시간만 지나면 재입력과는 상관없이 다시 받기 때문입니다.
반면 디바운싱은 제한시간 전에 입력이 들어오면 이전 것을 취소하고 다시 시간을 측정합니다. 결국 마지막 것만 실행하고 그 전에 들어온 것들은 모두 무시한다는 점에서 쓰로틀링과 다릅니다.
개인적으로 디바운싱은 마지막 것을 실행하기에 최신 값을 가져온다는 점에서 범용성이 커 보입니다. 제가 예시로 사용한 경우에서도 마지막에 입력한 아이디를 중복확인해야 하고 기타 검색이나 스크롤의 경우에서도 저의 최근 스크롤 정보가 필요할 수 있기 때문입니다.

해결코드

let count = 0;

let timer;

window.addEventListener(
  "scroll",
  // 이벤트 핸들러 함수
  function () {
    // 기존 타이머가 있다면 취소한다
    clearTimeout(timer);

    timer = setTimeout(function () {
      count++; // 디바운싱 카운트 증가
      const nav = document.getElementById("top_nav");
      const content = document.getElementById("nav_container");
      const contentRect = content.getBoundingClientRect();

      console.log(count);

      if (contentRect.bottom > 0) {
        // content가 화면 안에 있을 때
        nav.style.visibility = "hidden"; // nav를 화면 상단에 고정
        nav.style.zIndex = "-1";
      } else {
        // content가 화면 밖으로 나갔을 때
        nav.style.visibility = "visible"; // nav를 화면 위로 사라지게 함
        nav.style.zIndex = "10";
      }
    }, 50); // 500 밀리초 후에 실행될 로직
  }
);

다음과 같이 코드를 수정하면 훨씬 이벤트를 적게 호출할 수 있습니다.


스크롤 횟수는 동일한데 차이가 어마어마하게 나는 것을 위의 사진을 통해 확인해볼 수 있습니다.

느낀점

시간적으로도 500밀리초만 디바운싱을 걸어도 20배정도의 차이를 낼 수 있다는 것이 정말 신기했습니다.
시간 설정에 있어서 여러번 하면서 제가 체감상 불편하지 않을 정도의 시간을 찾았었는데 개인적으로 500밀리초 정도까지는 참아줄만 했습니다.
중복체크나 기타 디바운싱 관련 시간의 허용범위가 얼마나 될지 궁금해서 관련된 정보를 찾아봤습니다.
https://stackoverflow.com/questions/42361485/how-long-should-you-debounce-text-input

One important number to keep in mind is 250ms - this represents the (roughly) median reaction time of a human and is generally a good upper bound within which you should complete any user interface updates to keep your site feeling responsive. You can view some more information on human reaction times here.

사람에게 평균적으로 적절한 반응 시간이 대략 250ms 라고 하네요.
그 외에도 연결되어 있는 서버의 상태, 처리 비용과도 맞닿아 있다는 점도 매우 흥미롭습니다.

주어진 환경에서 사용자에게 최상의 서비스 환경을 제공하기위해 노력해오신 개발자 분들 덕분에 정말 편하게 다양한 서비스를 이용하고 있는 것 같습니다.
저도 열심히 학습해서 좋은 서비스를 만드는 개발자가 되고 싶습니다.

감사합니다.

profile
프론트 공부중입니다!

0개의 댓글