스파르타코딩클럽 내일배움캠프 TIL65

한재창·2023년 1월 31일
0

Throttling & Debouncing

Throttling

  • 짧은 시간 간격으로 연속해서 발생한 이벤트들을 일정시간 단위(delay)로 그룹화하여 처음 또는 마지막 이벤트 핸들러만 호출되도록 하는 것
    ex) 무한스크롤

Debouncing

  • 짧은 시간 간격으로 연속해서 이벤트가 발생하면 이벤트 핸들러를 호출하지 않다가 마지막 이벤트로부터 일정 시간(delay)이 경과한 후에 한 번만 호출하도록 하는 것
    ex) 입력값 실시간 검색, 화면 resize 이벤트

메모리 누수(Memory Leak)

  • 필요하지 않은 메모리를 계속 점유하고 있는 현상
  • setTimeout 이 메모리 누수(Memory Leak)를 유발하는 지?
    • 상황에 따라 메모리 누수를 일으킬 수도 있고 아닐 수도 있다.
    • 하나의 페이지에서 페이지 이동 없이 setTimeout을 동작시키고 타이머 함수가 종료될 때까지 기다린다면 메모리 누수는 없다.
    • 리액트로 만든 SPA 웹사이트는 페이지 이동 시 컴포넌트가 언마운트 됩니다.
    • 그런데 페이지 이동 전에 setTimeout 으로 인해 타이머가 동작중인 상태에서 clearTimeout을 안해주고 페이지 이동 시 컴포넌트는 언마운트 되었음에도 불구하고 타이머는 여전히 메모리를 차지하고 동작하고 있다. 이 경우 메모리 누수(Memory Leak)에 해당한다고 말할 수 있다.
import { useEffect, useState } from "react";

type ControlDelay = (delay: number) => void;

export default function App() {
  let timer: NodeJS.Timeout | null = null;

  // Throttling
  const throttle: ControlDelay = (delay) => {
    if (timer) {
      return;
    }
    console.log(`${(delay/1000).toFixed(1)}초 동안 추가요청 안받음`);
    timer = setTimeout(() => {
      console.log(`${(delay/1000).toFixed(1)}초 지남 추가요청 받음`);
      timer = null;
    }, delay);
  };

  // Debouncing
  const debounce: ControlDelay = (delay) => {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      console.log(`마지막 요청으로부터 ${(delay/1000).toFixed(1)}초 지났으므로 실행`);
      timer = null;
    }, delay);
  };

  useEffect(() => {
    return () => {
      // 페이지 unmount 시 실행
      // 메모리 누수 방지
      if (timer) {
        clearTimeout(timer);
      }
    };
  }, [timer]);

  return (
    <div>
      <button onClick={() => throttle(1000)}>쓰로틀링</button>
      <button onClick={() => debounce(1000)}>디바운싱</button>
    </div>
  );
}

export default App;

✅ 체크 리스트

  • Throttling 이 무엇인지 설명할 수 있다.
    • 서버에 많은 요청을 주지 않기 위해 처음이나 마지막 이벤트 아니면 처음과 마지막 이벤트가 발생하였을 때에만 함수를 실행한다.
  • Debouncing 이 무엇인지 설명할 수 있다.
    • 연속적으로 이벤트가 발생하면 호출하지 않다가 마지막 이벤트에만 호출되는 것
  • lodash 를 이용하여 쓰로틀링과 디바운싱을 적용할 수 있다.
    • 연습이 필요할 듯
  • 리액트에서 Throttling/Debouncing 시 useCallback을 적용하는 이유를 설명할 수 있다.
    • useCallback을 사용하는 이유는 이전에 호출했던 함수를 반복적으로 호출할 수 있게 하기 위해서이다.
profile
취준 개발자

0개의 댓글