본문 바로가기

공부/TIL

[TIL] 24.07.17 쓰로틀링(성능 측정)

반응형

Throttling 이란? 📖

짧은 시간 간격으로 연속해서 이벤트가 발생했을 때, 과도한 이벤트 핸들러 호출을 방지하는 기법입니다. 

 

 

1. 쓰로틀링 (throttling)

일정 주 동안 이벤트 핸들러를 한 번만 실행하도록 제어하는 것

 

일정한 간격으로 한 번만 실행하는 기법이기 때문에 이벤트 처리를 제어하고, 성능 향상을 할 수 있습니다.

예를 들면 스크롤 이벤트가 발생할 때 이벤트가 너무 많이 발생하면 성능 저하 문제가 생길 수 있기 때문에 이때 쓰로틀링을 적용하면 일정 주기 동안 이벤트를 제어하기 때문에 성능을 개선할 수 있습니다.

 

그래서 팀 소개 프로젝트에 쓰로틀링을 적용해보려고 합니다.

 

사용 방법

실제로 작성한 코드 입니다.

const throttleCallback = () => {
  const scrollTop = document.documentElement.scrollTop;
  const scrolled = (scrollTop / height) * 100;
  console.log(scrolled)
  progressBar.style.width = `${scrolled}%`;
}

const throttledScroll = (callback, delay) => {
  let timer;

  return () => {
    if(timer) return;

    timer = setTimeout(() => {
      callback();
      timer = null;
    }, delay)
  }
}

window.addEventListener("scroll", throttledScroll(throttleCallback, 16));

 

 

  • scroll 이벤트 발생 시 throttledScroll 함수를 호출해 콜백함수딜레이 시간을 전달합니다.
window.addEventListener("scroll", throttledScroll(throttleCallback, 16));

 

 

  • throttledScroll 함수 내부적으로 타이머를 실행해 일정 시간 delay (200ms)이 지난 후에 콜백함수를 실행합니다.
const throttledScroll = (callback, delay) => {
  let timer;

  return () => {
    if(timer) return;

    timer = setTimeout(() => {
      callback();
      timer = null;
    }, delay)
  }
}

 

 

  • 이후 콜백함수 실행 후 timer를 null로 바꿔주기 때문에 중간에 새로운 이벤트가 발생 시 return 하게 됩니다!
if(timer) return;

 

어려웠던 점

1. Throttling과 debouncing의 차이점

결국 이 둘의 차이점은 이벤트를 언제 발생시킬지의 시점 차이입니다.

 

debounce는 이벤트가 끝날 때까지 기다리지만,
throttle은 이벤트가 시작되면 일정 주기로 계속 실행합니다.

 

 

2. Throttling에서의 delay 시간 설정

1초는 1000밀리 초(ms)입니다. 일반적인 화면에서 프레임 속도는 60 프레임/초 (FPS)를 목표로 합니다. 

 

프레임 당 시간

 

즉, 60 FPS를 유지하려면 한 프레임을 그리는데 최대 16.67ms를 넘지 않는 게 좋다고 하는데 여기서 의문점이 생겼습니다!? 

각 프레임에 영향을 미치지 않도록 하려면 delay 시간을 16.67ms 이하로 설정해야 하는데 너무 작은 delay 시간은 Throttling의 사용 의미가 있을까?라는 생각을 하게 되었습니다. 프로젝트에 적용시킨 상단 스크롤 바 같은 경우에는 부드럽게 보여야 하기 때문에 16ms 이하가 아닌 50 ~ 100ms 사이의 delay 시간을 설정하게 되면 스크롤 바가 끊겨서 보이는 현상이 발생했습니다

 

 

그래서 performance.now() 메서드를 이용해 함수 간 실행 시점 차이를 비교해 봤습니다.

let timebase;

const throttleCallback = () => {
  if(timebase){
    console.log(performance.now() - timebase)
  }
  timebase = performance.now();
}
performance.now()
- 웹 페이지 성능 측정에 사용하기 위해 밀리초 미만의 해상도로 타임스탬프를 제공합니다.

 

실행 시점 차이

 

출력해 본 결과 6, 23, 7382ms... 등등 16ms 이하로 찍히는 콘솔들을 발견했습니다! 사용 의미가 있을까? -> YES~!!

 

깨달은 점

1. 성능 최적화를 위한 시간 계산

console.time(), console.timeEnd()

const throttleCallback = () => {
  console.time("scroll")
  const scrollTop = document.documentElement.scrollTop;
  const scrolled = (scrollTop / height) * 100;
  progressBar.style.width = `${scrolled}%`;
  console.timeEnd("scroll");
}

 

  • throttleCallback 함수가 실행된 시간을 console 창에 찍어줍니다.

throttleCallback 함수 실행 시간

 

performance.now()

let timebase;

const throttleCallback = () => {
  if(timebase){
    console.log(performance.now() - timebase)
  }
  timebase = performance.now();
}

 

  • throttleCallback 함수 간 실행 시점 차이을 console 창에 찍어줍니다.

실행 시점 차이

 

회고 🧐

화면 프레임이 끊기지 않도록 하기 위해서 Throttling에서 적절한 delay 시간을 설정하는 것이 중요하다는 생각을 했습니다.
결국 어떤 기능을 구현할 것이냐를 잘 고려해서 사용하면 좋을 것 같다는 생각을 했습니다!


출처 🏷️

 

 

Debounce – How to Delay a Function in JavaScript (JS ES6 Example)

In JavaScript, a debounce function makes sure that your code is only triggered once per user input. Search box suggestions, text-field auto-saves, and eliminating double-button clicks are all use cases for debounce. In this tutorial, we'll learn how to cre

www.freecodecamp.org

 

 

Performance: now() method - Web APIs | MDN

The performance.now() method returns a high resolution timestamp in milliseconds. It represents the time elapsed since Performance.timeOrigin (the time when navigation has started in window contexts, or the time when the worker is run in Worker and Service

developer.mozilla.org

 

반응형

'공부 > TIL' 카테고리의 다른 글

옵저버 패턴 알아보기  (0) 2024.09.10
[TIL] 24.07.18 Swiper 슬라이드  (0) 2024.07.18
[TIL] 24.07.16 코딩 컨벤션이란?  (0) 2024.07.16
[TIL] 24.07.15  (0) 2024.07.15
[TIL] 24.07.09 백준 10844번 js  (0) 2024.07.09
[TIL] 24.07.08  (0) 2024.07.08
[TIL] 24.06.17 백준 1373번 js  (0) 2024.06.17
[TIL] 24.06.12 백준 1676번 js  (2) 2024.06.12