개요

x축으로 스크롤되는 컴포넌트를 만들던 중 화면 크기에 따라 초기 컴포넌트 위치를 조절하는 코드를 작성하였습니다. 화면을 늘리고 줄여보았는데 이때 컴포넌트 위치가 브라우저 화면 크기에 따라 반응하는 것은 좋았지만 늘리고 줄일때마다 계속해서 발생하다보니 성능 문제 뿐만 아니라 위치가 계속 수정되며 어지럽게 동작하는 것이 매우 불편하였고 해결하고자 했습니다

 

이벤트를 텀을 둬서 실행시키기

우선 js에서 setInterval과 setTimeout이 생각났고 좀 더 찾아보던 중 resize와 관련된 방식으로 throttle, debounce를 사용할 수 있다는 것을 확인하였고 이벤트 핸들러가 많이 발생하는 연산에 제약을 걸어 제어할 수 있는 수준으로 이벤트를 발생시키는 것을 말한다고 합니다

 

throttle과 debouce는 기능적으로는 유사해보이기도 해서 따로 정리를 해보면

 

throttle

쓰로틀이란 이벤트를 일정한 주기마다 발생하도록 하는 방식으로써 하나의 이벤트가 연속적으로 많이 발생한다 하여도 쓰로틀에 설정해둔 시간 주기에 따라서만 발생하게 됩니다. 스크롤이 이동할 때 설정해둔 함수가 실행된다고 가정했을 때 스크롤이 시작부터 멈출때까지 지정해둔 함수가 계속해서 동작하는게 아닌 스크롤을 움직이기 시작한 뒤, 설정해둔 주기만큼 실행되고 스크롤이 멈추게 되었을 때 종료되는 방식을 가지고 있습니다.

 

한줄로 정리하면 실행 횟수에 제한을 거는 방식이라고 이해할 수 있습니다

 

const throttle = (fn, wait) => {
  let inThrottle, lastFn, lastTime;
  return function() {
    const context = this,
      args = arguments;
    if (!inThrottle) {
      fn.apply(context, args);
      lastTime = Date.now();
      inThrottle = true;
    } else {
      clearTimeout(lastFn);
      lastFn = setTimeout(function() {
        if (Date.now() - lastTime >= wait) {
          fn.apply(context, args);
          lastTime = Date.now();
        }
      }, Math.max(wait - (Date.now() - lastTime), 0));
    }
  };
};

window.addEventListener(
  'resize',
  throttle(function(evt) {
    console.log(window.innerWidth);
    console.log(window.innerHeight);
  }, 250)
); // Will log the window dimensions at most every 250ms

브라우저 resize를 감지해서 콘솔에 출력하게 되는데 250ms마다 출력됨

 

 

https://www.30secondsofcode.org/js/s/throttle

 

Throttle function - 30 seconds of code

Creates a throttled function that only invokes the provided function at most once per every wait milliseconds

www.30secondsofcode.org

 

 

Debounce

디바운스란 이벤트를 그룹화하여 특정시간이 지난 후 하나의 이벤트만 발생하도록 하는 기술이며 순차적 호출을 하나의 그룹으로 그룹화 할 수 있다고 한다.

 

아무리 많은 이벤트가 발생해도 실제 실행되는 것은 설정해둔 시간이 지난 뒤이며 그룹화시키기 때문에 한번밖에 실행되지 않는다 

const debounce = (fn, ms = 0) => {
  let timeoutId;
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn.apply(this, args), ms);
  };
};
window.addEventListener(
  'resize',
  debounce(() => {
    console.log(window.innerWidth);
    console.log(window.innerHeight);
  }, 250)
); // Will log the window dimensions at most every 250ms

 

 

throttle과 debounce 비교

 

정리해보자면

 

쓰로틀은 이벤트가 10초간 진행됐고 쓰로틀로 설정해둔 시간이 1초라면 1초 마다 쓰로틀에 설정해둔 함수가 실행된다고 이해했습니다. 그림으로 그려보자면 다음과 같습니다.

 

 

파란색이 수행된 작업이며 이벤트가 진행되는 동안 실행된다.

 

디바운스는 위와 같은 조건에서 설정해둔 시간이 1초라면 이벤트가 종료되었을 때 하나의 이벤트만 발생하도록 하는 방법이라고 이해했습니다

 

실제 예시 / 사용 사례

 

쓰로틀

 -  무한 스크롤 : footer 위치에 따라 새로 데이터를 불러와야 하는데 위치를 계속 계산하기엔 성능적으로 문제가 생기고 디바운스를 걸기엔 스크롤이 완전히 끝나야 실행되기 때문에 쓰로틀이 매우 적합합니다

유튜브 무한 스크롤 중..

 

 

디바운스

 - Ajax 요청 : 구글에서 검색을 하려고 검색어를 입력했을 때  엔터를 치거나 검색어를 완전히 입력하지 않았음에도 연관검색어가 출력된다 하지만 이렇게 보여주려면 항상 Input에 변화가 생기는 것을 감지해야하고 이 변화가 발생했을 때마다 ajax요청을 보내야하는데 이런 쿼리 하나하나가 구글지도같이 쿼리 요청 횟수에 따라 많은 비용이 발생하는 등 문제가 생길 수 있기때문에 디바운스를 사용한다

 

 

 

참고

 

https://webclub.tistory.com/607

 

디바운스(Debounce)와 스로틀(Throttle ) 그리고 차이점

Throttle, Debounce & Difference 스로틀(Throttle) 과 디바운스(Debounce) 란 무엇일까? 이 두 가지 방법 모두 DOM 이벤트를 기반으로 실행하는 자바스크립트를 성능상의 이유로 JS의 양적인 측면, 즉 이벤트(ev.

webclub.tistory.com

 

https://velog.io/@ktthee/React-18-%EC%97%90-%EC%B6%94%EA%B0%80%EB%90%9C-useDeferredValue-%EB%A5%BC-%EC%8D%A8-%EB%B3%B4%EC%9E%90

 

React 18 에 추가된 useDeferredValue, useTransition 을 써 보자

react 18 이 자랑하는 concurrent rendering, 써 보자!

velog.io

https://velog.io/@yes3427/Debounce-and-Throttle

 

디바운스(Debounce)와 스로틀(Throttle) 차이점

어제 무한 스크롤을 구현하면서 공부했던 부분이다. 한번 더 개념을 짚고 넘어가보도록 하자😎 DOM 이벤트를 기반으로 실행하는 JavaScript를 성능을 고려하여 양적인 측면, 즉 이벤트를 제어(제한

velog.io

 

'TIL > 개념정리' 카테고리의 다른 글

Docker에 대해서  (0) 2022.09.07
NextJS 간단 정리  (2) 2022.09.06
React-query useMutation 간단히 사용해보고 정리  (0) 2022.08.18
Git, Github 정리  (0) 2022.07.29
DB 트랜잭션에 대해서  (0) 2022.07.27
복사했습니다!