<aside> 🚩 [학습 목표]

  1. throttling과 debouncing의 개념에 대해 이해합니다.
  2. lodash를 이용하여 throttling과 debouncing을 적용할 수 있습니다.
  3. 리액트에서 throttling과 debouncing 시 useCallback을 적용하는 이유를 설명할 수 있습니다.

</aside>

1. Throttling & Debouncing이란?

짧은 시간 간격으로 연속해서 이벤트가 발생했을 때 과도한 이벤트 핸들러 호출을 방지하는 기법인 쓰로틀링과 디바운싱에 대해 학습해 봅시다. Timer Web API 중 setTimeout 메소드를 사용하여 쓰로틀링과 디바운싱을 각각 구현해보고 원리를 이해하고 적용하실 줄 알아야 합니다.

2. 실습

react-router-dom 설치

yarn add react-router-dom

App.jsx

import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "pages/Home";
import Company from "pages/Company";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
				<Route path="/company" element={<Company />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

src > pages > Home.jsx

import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";

export default function Home() {
  // const [state, setState] = useState(false);
  const navigate = useNavigate();
  let timerId = null;

  // Leading Edge Throttling
  const throttle = (delay) => {
    if (timerId) {
      // timerId가 있으면 바로 함수 종료
      return;
    }
    // setState(!state);
    console.log(`API요청 실행! ${delay}ms 동안 추가요청 안받음`);
    timerId = setTimeout(() => {
      console.log(`${delay}ms 지남 추가요청 받음`);
      // alert("Home / 쓰로틀링 쪽 API호출!");
      timerId = null;
    }, delay);
  };

  // Trailing Edge Debouncing
  const debounce = (delay) => {
    if (timerId) {
      // 할당되어 있는 timerId에 해당하는 타이머 제거
      clearTimeout(timerId);
    }
    timerId = setTimeout(() => {
      // timerId에 새로운 타이머 할당
      console.log(`마지막 요청으로부터 ${delay}ms지났으므로 API요청 실행!`);
      timerId = null;
    }, delay);
  };

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

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

src > pages > Company.jsx

import React from 'react;

export default function Company() {
  return (
    <div>
	    Test Page
    </div>
  );
}

3. lodash 적용 및 useCallback을 써야하는 이유 알아보기