티스토리 뷰

✅ 쓰로틀링과 디바운싱은 모두 웹에서 발생하는 이벤트를 제어하는 방법으로 불필요한 이벤트가 호출되는 것을 방지합니다. 예를 들어 검색어 자동완성 기능, 스크롤 관련 동작과 같은 이벤트에서 매번 입력, 스크롤에 대한 콜백이 발생하고 계속해서 콜백을 수행하는 일은 큰 리소스를 요구하기 때문에 서비스의 성능 저하 및 사용자 경험 저하를 야기합니다. 따라서 상황에 맞게 쓰로틀링이나 디바운싱을 적용하면 최적화하는데 큰 도움이 됩니다.


📌 쓰로틀링(throttling)

  • 쓰로틀링은 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 제어하는 것 입니다.
  • 개발자가 몇 초마다 한 번씩 실행되게 제한을 두는 것입니다.
  • 주로 스크롤 이벤트에서 많이 사용합니다.

 

쓰로틀링 구현 포인트 !

1. 함수가 실행 중인지 체크하는 타이머 변수를 생성
2. 함수를 호출하면 타이머를 동작시키기
3. 일정 시간 내에 함수가 다시 호출되면 실행되지 않게 처리를 해야 하므로 타이머 값이 없을 때만 함수 동작시키기
4. 함수가 완료되면 타이머를 다시 초기화하여 함수 호출이 가능하도록 처리하기

 

[ 쓰로틀링 적용 전 ] (코드는 더보기에서!)

 

더보기
import React, { useState, useEffect, useRef } from "react";

function App() {
  const divRef = useRef<HTMLDivElement>(null);

  const scrollFunc = (): void => {
    console.log(divRef.current?.scrollTop);
  };

  useEffect(() => {
    const divRefValue = divRef.current ? divRef.current : null;

    divRefValue?.addEventListener("scroll", scrollFunc);

    return () => {
      divRefValue?.removeEventListener("scroll", scrollFunc);
    };
  });

  return (
    <div className="App">
      <div
        ref={divRef}
        style={{
          position: "fixed",
          overflow: "scroll",
          width: "80%",
          height: "80%",
        }}
      >
        <div
          style={{
            height: "300%",
            background: "lightgreen",
          }}
        ></div>
      </div>
    </div>
  );
}

export default App;

 

쓰로틀링 적용 전

  • 위와 같이 스크롤 이벤트는 스크롤링할 때마다 발생하는데, 만약 이때마다 어떤 작업을 실행하게 된다면 성능 문제가 발생할 가능성이 클 것입니다.

 

[ 쓰로틀링 적용 후 ] (코드는 더보기에서!)

 

더보기
import React, { useState, useEffect, useRef } from "react";

function App() {
  const divRef = useRef<HTMLDivElement>(null);
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null); // 쓰로틀링을 체크할 timer

  /* 쓰로틀링 적용 */
  const scrollFunc = (): void => {
    // timer가 없을 때
    if (!timer.current) {
      timer.current = setTimeout(() => {
        console.log(`scrollTop :: ${divRef.current?.scrollTop}`);
        timer.current = null; // 로직이 끝나면 timer를 초기화
      }, 250);
    }
  };

  useEffect(() => {
    const divRefValue = divRef.current ? divRef.current : null;

    divRefValue?.addEventListener("scroll", scrollFunc);

    return () => {
      divRefValue?.removeEventListener("scroll", scrollFunc);
    };
  });

  return (
    <div className="App">
      <div
        ref={divRef}
        style={{
          position: "fixed",
          overflow: "scroll",
          width: "80%",
          height: "80%",
        }}
      >
        <div
          style={{
            height: "300%",
            background: "lightgreen",
          }}
        ></div>
      </div>
    </div>
  );
}

export default App;

 

쓰로틀링 적용 후

  • 쓰로틀링을 적용한 결과 스크롤 이벤트를 일정 시간마다 호출하도록 제어할 수 있게 되었습니다!

 

📌 디바운싱(debouncing)

  • 디바운싱은 연속으로 호출되는 함수들 중 마지막에 호출되는 함수(또는 제일 처음 호출한 함수)만 실행되도록 하는 것입니다.
  • 이벤트를 그룹화하여 특정 시간이 지난 후 하나의 이벤트만 발생하도록 제어합니다.
  • 주로 사용자 입력 이벤트 처리 (검색어 자동완성), 리사이즈(Resize) - 브라우저 창 크기 조절 이벤트에 많이 사용합니다.

 

디바운싱 구현 포인트 !

1. 함수가 실행 중인지 체크하는 타이머 변수를 생성
2. 함수를 호출하면 타이머를 동작시키기
3. 일정 시간 전에 함수 호출이 발생하면, 기존 타이머를 취소하고 시간을 재설정하여 새로운 함수 호출

 

[ 디바운싱 적용 전 ] (코드는 더보기에서!)

 

더보기
import React, { useState, useEffect, useRef } from "react";

function App() {
  const inputRef = useRef<HTMLInputElement>(null);

  const inputFunc = (): void => {
    console.log(inputRef.current?.value);
  };

  return (
    <div className="App">
      <div
        style={{ position: "absolute", width: "50%", margin: "10% 25% 0 25%" }}
      >
        <input ref={inputRef} onChange={inputFunc}></input>
      </div>
    </div>
  );
}

export default App;

 

쓰로틀링 적용 전

  • 위와 같이 인풋 이벤트는 입력할 때마다 발생하는 것을 확인할 수 있습니다. 따라서 예를 들어 사용자 입력에 따른 검색어 자동완성 기능을 구현하고자 한다면 필요 없는 API들을 상당히 많이 호출을 할 것입니다.

 

[ 디바운싱 적용 후 ] (코드는 더보기에서!)

 

더보기
import React, { useState, useEffect, useRef } from "react";

function App() {
  const inputRef = useRef<HTMLInputElement>(null);
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

  /* 디바운싱 적용 */
  const inputFunc = (): void => {
    if (timer.current) {
      clearTimeout(timer.current);
    }

    timer.current = setTimeout(() => {
      console.log(inputRef.current?.value);
    }, 250);
  };

  return (
    <div className="App">
      <div
        style={{ position: "absolute", width: "50%", margin: "10% 25% 0 25%" }}
      >
        <input ref={inputRef} onChange={inputFunc}></input>
      </div>
    </div>
  );
}

export default App;

 

디바운싱 적용 후

  • 디바운싱을 적용한 결과 인풋 이벤트가 설정한 시간 동안 발생하지 않았을 때 마지막 이벤트를 호출하는 것을 확인할 수 있습니다!

 

📌 쓰로틀링(throttling) 과 디바운싱(debouncing) 의 차이점

 

  • 쓰로틀링은 연속되는 이벤트의 경우 설정한 특정 시간을 주기로 이벤트를 계속 실행합니다.
  • 디바운싱은 연속되는 이벤트의 경우 모두 무시하고 설정한 특정 시간 동안 이벤트가 발생하지 않았을 때 맨 마지막 이벤트를 딱 한번 실행합니다.

 

🤔  정리 !

  • 쓰로틀링과 디바운싱 모두 이벤트를 제어하는 방법으로 불필요한 이벤트가 연속으로 호출되는 것을 방지하여 서비스의 성능 향상 및 사용자 경험 최적화에 사용됩니다.
  • 쓰로틀링은 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 제어하는 것입니다.
  • 디바운싱은 연속으로 호출되는 함수들 중 마지막에 호출되는 함수(또는 제일 처음 호출한 함수)만 실행되도록 하는 것입니다.
  • 쓰로틀링과 디바운싱의 차이점은  연속되는 이벤트에서 쓰로틀링은 적어도 X 초마다 정기적으로 기능 실행을 보장하나, 디바운싱은 모두 무시하고 특정 시간 동안 이벤트가 발생하지 않았을 때 마지막 이벤트를 딱 한번 실행합니다.

 

 

🔗 참고한 

 

How to Optimize web app with Debounce and Throttle

In optimizing a product's performance, engineers end up designing a process that does the most with the least. This either by finding a way to minimize an appli

blog.knoldus.com

'JavaScript' 카테고리의 다른 글

JS - 1급 객체 (First Class Object)  (0) 2022.12.04
JS - 동작원리와 비동기처리  (1) 2022.11.11
Default Export / Named Export ?  (2) 2022.07.27
정규 표현식 (Regular Expression)  (3) 2022.07.18
시맨틱 웹(Semantic Web) ?  (2) 2022.07.16
댓글