20230222 [react] - throttling &debouncing

lionloopy·2023년 2월 22일
0

리액트

목록 보기
17/18

throttling & debouncing

:짧은 시간 간격으로 연속해서 이벤트가 발생했을 때, 과도한 이벤트 핸들러 호출을 방지하는 기법이다.
(setTimeout메소드를 사용하여 구현할 수 있다.)

throttling


1.이벤트가 일어난 첫번째에 함수를 일으킨다.

2.이벤트가 일어나고, 마지막에 함수를 일으킨다.

3.이벤트의 처음과 마지막에 함수를 일으킨다.

:이벤트는 막 일어나지만, 호출은 한 번 되는 현상이다.
짧은 시간 간격으로 연속해서 발생한 이벤트들을 일정시간 단위로 그룹화하여, 처음 또는 마지막에 이벤트 핸들러만 호출되도록 하는 것

  • 무한스크롤(스크롤을 내릴 때 마다 서버에 요청되면 과부하)

코드

import React from "react";

function Home() {
  let timerId = null;
  const throttle = (delay) => {
    if (timerId) {
      return;
    }
    console.log("bye");
    timerId = setTimeout(() => {
      console.log("실행중");
      timerId = null;
    }, delay);
  };

  return (
    <div style={{ paddingLeft: 20, paddingRight: 20 }}>
      <h1>이벤트 예제</h1>
      <button onClick={() => throttle(2000)}>쓰로틀링 버튼</button>
      <button onClick={() => debounce(2000)}>디바운싱 버튼</button>
    </div>
  );
}

export default Home;

1.setTimeout을 사용할 땐 id가 필요하다. 항상 어떠한 값을 반환하는데 그 값을 throttle과 debounce를 조작할 때 사용할 것이다. 이게 바로 timerId이다.
2.처음에 timerId값에 null을 주고 button을 클릭하면 onClick에 의해 throttle함수가 호출된다. 이때 매개변수로 우리는 2000(2초)를 주었다.
3.throttle함수에서 delay값(2000)을 받고, timerId가 null이니까 setTimeout함수가 실행된다.
4.이때 timerId값이 있으면 그냥 return하고 없으면 setTimeout함수를 실행시킨다.
5.delay만큼 뒤에 timerId값을 다시 null로 만들어준다.
6.아무리 연속해서 눌러도, 누른만큼 콘솔이 찍히는 것이 아닌, 2초가 지나면 콘솔을 찍게 된다.

debouncing


이벤트들이 바운싱이 되면서 호출되는 것(전등 타다닥!)
:짧은 시간 간격으로 연속해서 이벤트가 발생하면, 이벤트 핸들러를 호출하지 않다가 마지막에 이벤트로부터 일정시간(delay)이 경과한 후에 한 번만 호출하도록 하는 것

  • 창의 크기를 계속 잡고 조절해 보았을 때, 계속해서 바뀌게 되면 과부하가 오게 된다. 따라서 창을 딱 놓은 마지막 한 번만 함수를 호출한다.

코드

import React from "react";

function Home() {
  let timerId = null;
  const throttle = (delay) => {};
  const debounce = (delay) => {
    if (timerId) {
      clearTimeout(timerId);
    }
    timerId = setTimeout(() => {
      console.log("hello");
      timerId = null;
    }, delay);
  };
  return (
    <div style={{ paddingLeft: 20, paddingRight: 20 }}>
      <h1>이벤트 예제</h1>
      <button onClick={() => throttle(2000)}>쓰로틀링 버튼</button>
      <button onClick={() => debounce(2000)}>디바운싱 버튼</button>
    </div>
  );
}

export default Home;

1.setTimeout을 사용할 땐 id가 필요하다. 항상 어떠한 값을 반환하는데 그 값을 throttle과 debounce를 조작할 때 사용할 것이다. 이게 바로 timerId이다.
2.처음에 timerId값에 null을 주고, button을 클릭하면 onClick에 의해 debounce함수가 호출된다. 이때 매개변수로 우리는 2000(2초)를 주었다.
3.debounce함수에서 delay값(2000)을 받고, timerId가 null이니까 setTimeout함수가 실행된다.
4.delay만큼 뒤에 hello라는 값을 찍고, 다시 timerId를 null값으로 바꾼다.
5.이때 우리가 여러번 연속으로 클릭하게 되면, 계속해서 hello가 출력되지 않는다. => debounce
6.여러번 연속 클릭하게 되면 timerId가 들어가 있는 상태가 되기 때문에, if문으로 들어가게 되고, clearTimeout으로 들어가게 된다. 그래서 다시 timerId가 재할당 되고, 다시 밑에 setTimeout이 실행되게 된다.
그래서 여러번 연속해서 눌러도 마지막에 1번만 결과값이 나온다.
=>2초를 기다리지 않고 누르는 순간 계속 초기화가 되는 것

메모리 누수 memory leak

:필요하지 않은 메모리를 계속 점유하고 있는 현상
위 만든 작업물은 2초 있다가 기능을 수행하게 된다. 그런데 만약 나는 버튼을 누르고 다른 페이지로 이동했다면? 그대로 다른 페이지에 있어도 그 작업물은 실행하고 있고, 2초 있다가 결과물을 내놓는다.
따라서 이때 메모리 누수를 막기 위해 useEffect의 return문을 활용한다.

  const navigate = useNavigate();

  useEffect(() => {
    return () => {
      if (timerId) {
        clearTimeout(timerId);
      }
    };
  }, []);
  -----------------------------
          <button
          onClick={() => {
            navigate("/company");
          }}
        >
          페이지 이동
        </button>

lodash

:low + dash = _
배열 등 다양한 데이터의 필수적인 구조를 쉽게 다룰 수 있게끔 하는데에 사용된다. 배열안의 객체들의 값을 핸들링 할 때 유용하다.
throwttle과 debounce를 최적화 시키기 위해서 사용한다.

import React, { useState } from "react";
import _ from "lodash";
import { useCallback } from "react";

function App() {
  const [search, setSearch] = useState();
  const [input, setInput] = useState();
  const handleSearch = useCallback(
    _.debounce((text) => {
      setSearch(text);
    }, 2000),
    []
  );
  const handleChange = (event) => {
    setInput(event.target.value);
    handleSearch(event.target.value);
  };

  return (
    <div>
      <h1>디바운싱 예제</h1>
      <input
        placeholder="디바운싱 할거야"
        type="text"
        onChange={handleChange}
      />
      <p>search text : {search}</p>
      <p>input text : {input}</p>
    </div>
  );
}

export default App;
  const debounce = (callback, delay) => {
    let timerId = null
    return(...args) => {
      if(timerId) clearTimeout(timerId)
      timerId = setTimeout(() => {
        callback(...args)
      },[delay])
    }
  }
profile
Developer ʕ ·ᴥ·ʔ ʕ·ᴥ· ʔ

0개의 댓글