JavaScript

[JavaScript] ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•ด๋ณด์ž ! Debouncing๊ณผ Throttling

Dana10 2025. 1. 14. 23:44

1. Debouncing (๋””๋ฐ”์šด์‹ฑ)

  • ๋งˆ์ง€๋ง‰ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋‚˜์„œ ์ผ์ •ํ•œ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ๋”์ด์ƒ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๋•Œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์‹คํ–‰๋œ ํ•จ์ˆ˜๋งŒ์„ ์‹คํ–‰ํ•จ.
  • ์ฆ‰ ์—ฐ์†์ ์œผ๋กœ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ํ•˜๋‚˜๋กœ ์ฒ˜๋ฆฌ.
  • ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ์ด๋‚˜ ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰ ์‹œ api ํ˜ธ์ถœ ํšŸ์ˆ˜๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ.
<body>
  <input type="text" />
  <div>
    <span>default : </span>
    <span id="default"></span>
  </div>
  <div>
    <span>debounce : </span>
    <span id="debounce"></span>
  </div>
</body>

 

document.querySelector('input').addEventListener('input',(e) => {
  const { value } = e.target;
  document.getElementById('default').innerText = value;
  debounce(value);
})


const debounceFunc = (cb,delay) => {
  let timeout;
  return (...arg) => {
   clearTimeout(timeout);
   timeout = setTimeout(() => cb(...arg),delay)
  }
}

const debounce = debounceFunc((value) => {
  document.getElementById('debounce').innerText = value;
},1000);

 

์œ„์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด input์— ํƒ€์ดํ•‘์„ ํ•  ๋•Œ๋งˆ๋‹ค ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

default ํƒœ๊ทธ์˜ innerText๋Š” ์‹ค์‹œ๊ฐ„ ํƒ€์ดํ•‘์„ ๊ทธ๋Œ€๋กœ ๋žœ๋”๋ง ํ•œ๋‹ค.

๋ฐ˜๋ฉด debounce innerText๋Š” 1์ดˆ๊ฐ€ ์ง€๋‚œ ํ›„์—์•ผ ํƒ€์ดํ•‘ ๋‚ด์šฉ์„ ๋žœ๋”๋ง ํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์ด๋ฒคํŠธ๊ฐ€ ์—ฐ์†์œผ๋กœ ๋ฐœ์ƒํ•  ๋•Œ ์ผ์ • ์‹œ๊ฐ„(1์ดˆ)์ด ์ง€๋‚˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ์ด๋ฒคํŠธ๊ฐ€ ์—†๋‹ค๋ฉด

ํ•œ ๋ฒˆ์— ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋””๋ฐ”์šด์Šค๋ผ๊ณ  ํ•œ๋‹ค.

 

input์— ํƒ€์ดํ•‘์„ ํ•  ๋•Œ๋งˆ๋‹ค debounce(value)๊ฐ€ ํ˜ธ์ถœ๋˜๋Š”๋ฐ, ์ด๋Š” ์ฆ‰ debounceFunc๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

debouncFunc๋Š” ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ›„์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ

๋งŒ์•ฝ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ธฐ ์ „์— ๋˜๋‹ค์‹œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด

๊ธฐ์กด์— timeout์— ํ• ๋‹น๋˜์—ˆ๋˜ setTimeout ํ•จ์ˆ˜๊ฐ€ clearTimeout์— ์˜ํ•ด ์‚ฌ๋ผ์ ธ๋ฒ„๋ฆฐ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋˜ ์ƒˆ๋กœ์šด ํƒ€์ด๋จธ๊ฐ€ ๋งž์ถฐ์ง„๋‹ค.

 

์—ฌ๊ธฐ์„œ debounceFunc๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ, timeout์ด ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š๋‚˜?

๊ทธ๋Ÿผ clearํ•  ๊ฒƒ๋„ ์—†์ง€ ์•Š๋‚˜?

์•„๋‹ˆ ๊ทธ๋Ÿฌ๋ฉด 1000์ดˆ๋งˆ๋‹ค ๋ชจ๋“  ํ˜ธ์ถœ์„ ๋‹ค ์‹คํ–‰ํ•˜๊ฒ ๋„ค?!! ๊ทธ๊ฑด debounce๊ฐ€ ์•„๋‹Œ๋ฐ.. ?

 

์ด๋Ÿฐ ๋Šช์— ๋น ์ ธ๋ฒ„๋ ธ๋‹ค.

 

์ฝ”๋“œ๋ฅผ ์ฒœ์ฒœํžˆ ๋ถ„์„ํ•˜๋ฉฐ ๊ตฌ๊ธ€๋ง์„ ํ†ตํ•ด ๊ฒฐ๋ก ์„ ์–ป์—ˆ๋‹ค.

setTimeout์ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋กœ์ €๋กœ ์ธํ•ด ๊ธฐ์กด์˜ setTimeout์€ timeout์„ ๊ณ„์† ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ณ 

์ƒˆ๋กœ debounceFunc๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ timeout์ด ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๊ธฐ์กด์˜ setTimeout ํ•จ์ˆ˜๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ์ƒํƒœ์ธ ๊ฒƒ์ด๋‹ค.

 

๋”ฐ๋ผ์„œ clearTimeout์œผ๋กœ ๊ธฐ์กด์˜ setTimeout ํ•จ์ˆ˜๊ฐ€ ์‚ฌ๋ผ์ง€๊ณ ,

์ƒˆ๋กœ setTimeout์ด timeout์— ํ• ๋‹น๋œ๋‹ค.

 

์ด๋Ÿฌํ•œ ๊ณผ์ •์œผ๋กœ debounce๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


2. Throttling (์“ฐ๋กœํ‹€๋ง)

  • ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด 
  • ์ฆ‰ ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด
  • ์ผ์ • ์ฃผ๊ธฐ๊ฐ€ ์ง€๋‚˜์ง€ ์•Š์•˜๋Š”๋ฐ ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๋Š” ๋ฌด์‹œํ•จ
  • ์ฃผ๋กœ ์Šคํฌ๋กค์˜ ์œ„์น˜๋ฅผ ํ™œ์šฉํ•ด์„œ ๋ฌด์–ธ๊ฐ€ ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ
<body>
  <input type="text" />
  <div>
    <span>default : </span>
    <span id="default"></span>
  </div>
  <div>
    <span>throttle : </span>
    <span id="throttle"></span>
  </div>
</body>
document.querySelector('input').addEventListener('input',(e) => {
  const { value } = e.target;
  document.getElementById('default').innerText = value;
  throttle(value);
})

 let isThrottling;  
const throttleFunc = (cb,delay) => {
  return (...arg) => { 
    if(isThrottling) return;
  	isThrottling = true;
    setTimeout(() => {
      cb(...arg);
      isThrottling = false;
    },delay)
  }
}

const throttle = throttleFunc((value) => {
  document.getElementById('throttle').innerText = value;
},1000);

 

1. input์— ํƒ€์ดํ•‘์„ ํ•  ๋•Œ๋งˆ๋‹ค throttle(value);๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

2. throttle์—๋Š” trottleFunc์˜ ๋ฐ˜ํ™˜ ํ•จ์ˆ˜๊ฐ€ ํ• ๋‹น๋˜์–ด ์žˆ๋‹ค.

3. ์ตœ์ดˆ์˜ isThrottling์€ undefined์ด๊ธฐ ๋•Œ๋ฌธ์— return๋˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์‹คํ–‰๋œ๋‹ค.

4.isThrottling์ด true๋กœ ์žฌํ• ๋‹น๋œ๋‹ค.

5.setTimeoutํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

6.์—ฌ๊ธฐ์„œ๋Š” 1์ดˆ์˜ delay๋ฅผ ์ฃผ์—ˆ๋Š”๋ฐ, ๋งŒ์•ฝ 1์ดˆ ์•ˆ์— ๋˜๋‹ค์‹œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด

7.throttle(value)๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋œ๋‹ค.

8.์ด๋•Œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์ธ setTimeout์ด isThrottling์˜ ๊ฐ’์„ ํด๋กœ์ €์— ์˜ํ•ด ์•„์ง ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค.

9.๋”ฐ๋ผ์„œ ์ฝ”๋“œ ์ฒซ๋ฒˆ์งธ if๋ฌธ์—์„œ isThrottling์€ ์•„๊นŒ true๋กœ ์žฌํ• ๋‹น๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ true๋ผ์„œ ์ฝ”๋“œ๊ฐ€ ๋”์ด์ƒ ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  return๋œ๋‹ค.

10.๋งŒ์•ฝ 1์ดˆ๊ฐ€ ์ง€๋‚˜๋ฉด, setTimeout์˜ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๊ณ , ์ธ์ž๋กœ ๋ฐ›์€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๋งค๊ฐœ๋ณ€์ˆ˜(value)๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค.

11.๊ทธ๋ฆฌ๊ณ ๋‚˜์„œ isThrottling์— false๋ฅผ ์žฌํ• ๋‹นํ•œ๋‹ค.

12.์ „์—ญ ๋ณ€์ˆ˜ let isThrottling์ด false๋กœ ๊ฐ’์ด ๋ฐ”๋€Œ๊ณ ,

13.๋‹ค์‹œ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋œ๋‹ค๋ฉด ์œ„์™€ ๊ฐ™์€ ๊ณผ์ •(4๋ฒˆ ์ดํ›„)์„ ๋ฐ˜๋ณตํ•˜๊ฒŒ ๋œ๋‹ค.