온라인 게임에서 스킬 = 함수 라고 생각하기
함수가 너무 자주 호출될때 그 횟수를 제한하는 기술
만약 무거운 작업을 하는 함수라면 상당한 CPU 사용 혹은 서버 비용이 발생함
-> 자원 방지를 위해서 지나치게 자주 호출되는 것을 방지할 필요가 있음
즉, 쓰로틀링은 함수가 한번 호출되면 일정 시간이 지나기 전에 다시 호출되지 않도록 막는것임
(게임에서 쿨타임 끝나기 전에 다시 스킬 사용 못하는 상황과 비슷)
ThrottleHook
import { useState } from "react";
import "../ThrottleHook.css";
function hackLottoNumbers() {
console.log("행운의 로또 번호 생성중🍀");
const lottoNumbers = [];
for (let i = 0; i < 6; i++) {
const number = Math.floor(Math.random() * 45) + 1;
lottoNumbers.push(number);
}
return lottoNumbers;
}
function ThrottleHook() {
const [lottoNumbers, setLottoNumbers] = useState([0, 0, 0, 0, 0, 0]);
const handleClick = () => {
const result = hackLottoNumbers();
setLottoNumbers(result);
};
return (
<div className="container">
<h1 className="title">로또 번호 맞추자~!</h1>
<button className="button" onClick={handleClick}>
번호 맞추기
</button>
<div className="numbers">
{lottoNumbers.map((number, idx) => (
<span key={idx} className="number">
{number}
</span>
))}
</div>
</div>
);
}
export default ThrottleHook;
만약 사용자가 번호 맞추기 버튼을 계속 클릭하게 되면 hackLottoNumbers 함수가 엄청 많이 호출됨 -> 비용과 리소스 낭비
- 해결 방법 : 사용자가 많이 눌러도 함수가 지나치게 자주 호출되지 않도록 호출 횟수를 제한하기
-> 함수 호출 사이에 쿨타임 넣기 -> Throttle 사용
함수가 한 번 호출되면 1초동안 호출되지 못하도록 제한하기
함수가 호출된 시간을 기록하기 위해 lastRun 변수 생성하고 useRef사용하기
(state가 update 될 때 기록한 시간값이 초기화 되는 것을 막기 위해 useRef사용)
사용자가 버튼 클릭한 시간에서 lastRun 빼서 timeElapsed 변수에 담아주고 조건문 작성해주기
import { useState, useRef } from "react";
import "../ThrottleHook.css";
function hackLottoNumbers() {
console.log("행운의 로또 번호 생성중🍀");
const lottoNumbers = [];
for (let i = 0; i < 6; i++) {
const number = Math.floor(Math.random() * 45) + 1;
lottoNumbers.push(number);
}
return lottoNumbers;
}
function ThrottleHook() {
const [lottoNumbers, setLottoNumbers] = useState([0, 0, 0, 0, 0, 0]);
// state가 update 될 때 기록한 시간값이 초기화 되는 것을 막기 위해 useRef사용
const lastRun = useRef(Date.now());
const handleClick = () => {
const timeElapsed = Date.now() - lastRun.current;
if (timeElapsed >= 1000) {
const result = hackLottoNumbers();
setLottoNumbers(result);
lastRun.current = Date.now();
}
};
return (
<div className="container">
<h1 className="title">로또 번호 맞추자~!</h1>
<button className="button" onClick={handleClick}>
번호 맞추기
</button>
<div className="numbers">
{lottoNumbers.map((number, idx) => (
<span key={idx} className="number">
{number}
</span>
))}
</div>
</div>
);
}
export default ThrottleHook;
ThrottleHook
import { useState } from "react";
import { useThrottle } from "../hooks/useThrottle";
import "../ThrottleHook.css";
function hackLottoNumbers() {
console.log("행운의 로또 번호 생성중🍀");
const lottoNumbers = [];
for (let i = 0; i < 6; i++) {
const number = Math.floor(Math.random() * 45) + 1;
lottoNumbers.push(number);
}
return lottoNumbers;
}
function ThrottleHook() {
const [lottoNumbers, setLottoNumbers] = useState([0, 0, 0, 0, 0, 0]);
const handleClick = useThrottle(() => {
const result = hackLottoNumbers();
setLottoNumbers(result);
}, 1000);
return (
<div className="container">
<h1 className="title">로또 번호 맞추자~!</h1>
<button className="button" onClick={handleClick}>
번호 맞추기
</button>
<div className="numbers">
{lottoNumbers.map((number, idx) => (
<span key={idx} className="number">
{number}
</span>
))}
</div>
</div>
);
}
export default ThrottleHook;
useThrottle
import { useRef } from "react";
// delay - 쿨타임
export function useThrottle(callback, delay) {
// state가 update 될 때 기록한 시간값이 초기화 되는 것을 막기 위해 useRef사용
const lastRun = useRef(Date.now());
return () => {
const timeElapsed = Date.now() - lastRun.current;
if (timeElapsed >= delay) {
callback();
lastRun.current = Date.now();
}
};
}