Debounce & Throttle

โ˜๏ธ yeyoยท2022๋…„ 3์›” 29์ผ
0
post-thumbnail
post-custom-banner

Debounce์™€ Throttle

1. Debounce

๐Ÿ’กโž–โž–๐Ÿ’กโž–โž–๐Ÿ’กโž–โž–๐Ÿ’ก
โž–โž–โž–โž–โž–โž–โž–โž–โž–๐Ÿ’ก

๐Ÿ“– ์‚ฌ์ „์  ์˜๋ฏธ : ๊ธฐ๊ณ„์  ์Šค์œ„์น˜ ์„ผ์„œ๋‚˜ ํ„ฐ์น˜ ์„ผ์„œ ๋“ฑ์„ ๋‹ค๋ฃฐ ๋•Œ, ์ˆœ๊ฐ„์ ์œผ๋กœ ์Šค์œ„์น˜์˜ ์ ‘์ ์—์„œ ON/OFF๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š” ํ˜„์ƒ(debouncing)์„ ์—†์• ๋Š” ๊ฒƒ
๐Ÿ’ป ํ”„๋กœ๊ทธ๋ž˜๋ฐ์  ์˜๋ฏธ : ์ด๋ฒคํŠธ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ํŠน์ • ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ›„, ํ•˜๋‚˜์˜ ์ด๋ฒคํŠธ๋งŒ ๋ฐœ์ƒํ•˜๋„๋ก ํ•˜๋Š” ๊ธฐ์ˆ 
โœ”๏ธ ์‚ฌ์šฉ ์˜ˆ์‹œ) ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ์ด๋ฒคํŠธ์— ์ฃผ๋กœ ์‚ฌ์šฉ
๐Ÿ’ฌ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• : ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜์—ˆ์„ ๋•Œ ์ผ์ • ์‹œ๊ฐ„์„ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋งŒ๋“ค๊ณ , ์ผ์ • ์‹œ๊ฐ„ ๋‚ด์— ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ๋˜ ๋“ค์–ด์˜ค๋ฉด ์ด์ „ ์š”์ฒญ์„ ์ทจ์†Œํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

function debounce(callback, delay) {
    let timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
            callback.apply(this, arguments)
        }, delay)
    }
}

2. Throttle

๐Ÿ’กโž–โž–๐Ÿ’กโž–โž–๐Ÿ’กโž–โž–๐Ÿ’ก
โž–โž–โž–โž–๐Ÿ’กโž–โž–โž–โž–๐Ÿ’ก

๐Ÿ“– ์‚ฌ์ „์  ์˜๋ฏธ : ๋ชฉ์„ ์กฐ๋ฅด๋Š” ํ–‰์œ„. ์ถœ๋ ฅ์„ ์กฐ์ ˆํ•œ๋‹ค๋Š” ์˜๋ฏธ๋„ ์žˆ์–ด ๋ฐธ๋ธŒ๋ฅผ ์กฐ์ ˆํ•˜๋Š” ๊ณผ์ •์—์„œ๋„ ์ด ๋‹จ์–ด๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.
๐Ÿ’ป ํ”„๋กœ๊ทธ๋ž˜๋ฐ์  ์˜๋ฏธ : ์ผ์ • ์‹œ๊ฐ„๋™์•ˆ ์ผ์–ด๋‚œ ์ด๋ฒคํŠธ๋ฅผ ๋ชจ์•„ 1๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๋Š” ๊ธฐ์ˆ 
โœ”๏ธ ์‚ฌ์šฉ ์˜ˆ์‹œ) scroll, mousemove ์ด๋ฒคํŠธ์— ์ฃผ๋กœ ์‚ฌ์šฉ
๐Ÿ’ฌ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• : ํƒ€์ด๋จธ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜๊ณ , ํƒ€์ด๋จธ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์•„๋ฌด๋Ÿฐ ๋™์ž‘๋„ ํ•˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ ์ผ์ • ์‹œ๊ฐ„ ์ดํ›„์— ์ด๋ฒคํŠธ๊ฐ€ 1๋ฒˆ ์‹คํ–‰๋˜๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค.

function throttle(callback, delay) {
  let timer;
  return function () {
    if(!timer) {
      timer = setTimeout(() => {
        callback.apply(this, arguments)
      }, delay)
    }
  }
}

3. ์ฐจ์ด์ 

๋‘˜์˜ ์ฐจ์ด๋Š” Throttle์˜ ๊ฒฝ์šฐ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , Debounce๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํ’€์–ด์„œ ์„ค๋ช…ํ•ด๋ณด๋ฉด, Debounce๋Š” ์ผ์ • ์‹œ๊ฐ„ ๋‚ด์— ๋‹ค์‹œ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋  ๊ฒฝ์šฐ ํƒ€์ด๋จธ๊ฐ€ ์ดˆ๊ธฐํ™” ๋˜์–ด ๋‹ค์‹œ ์ผ์ • ์‹œ๊ฐ„๋งŒํผ ๊ธฐ๋‹ค๋ฆฌ์ง€๋งŒ, Throttle์€ ์ด๋ฒคํŠธ๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋Š” ๊ฒƒ๊ณผ๋Š” ์ƒ๊ด€ ์—†์ด ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Throttle์„ ๊ฒ€์ƒ‰์–ด ์ž…๋ ฅ์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ '๋ฒจ๋กœ๊ทธ'๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๊ฒ€์ƒ‰ ์‹œ ํƒ€์ด๋จธ์˜ ์‹œ๊ฐ„์ด ์งง์„ ๊ฒฝ์šฐ ๋ฒ , ๋ฒจใ„น,๋ฒจ๋กœ๊ทธ ์ด๋Ÿฐ ์‹์œผ๋กœ '๋ฒจ๋กœ๊ทธ'๋ผ๋Š” ๊ฒ€์ƒ‰์–ด ์ž…๋ ฅ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๋ฒˆ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ค‘๊ฐ„ ์ค‘๊ฐ„ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋„ ๋ฐœ์ƒ์‹œํ‚ค๊ธธ ์›ํ•  ๋•Œ์—๋Š” Throttle์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋‘ ๊ธฐ์ˆ ์ด ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉด ์•„๋ž˜ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ข‹๋‹ค. ๋‘˜์˜ ์ฐจ์ด๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
๋””๋ฐ”์šด์Šค(Debounce)์™€ ์Šค๋กœํ‹€(Throttle ) ๊ทธ๋ฆฌ๊ณ  ์ฐจ์ด์ 

4. ์ฝ”๋“œ ๋ถ€๊ฐ€ ์„ค๋ช…

Closure

debounce๋‚˜ throttle๋Š” ํด๋กœ์ €(Closure) ํ•จ์ˆ˜๋กœ, ๋‚ด๋ถ€์˜ ์ต๋ช…ํ•จ์ˆ˜๋Š” ์ž์‹ ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ์™ธ๋ถ€ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ํด๋กœ์ € ์˜ˆ์ œ์ฝ”๋“œ

function outer() {
  var x = 1;
  var inner = function () { console.log(x); };
  return inner;
}

var test = outer();
test(); // 1

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด, ์™ธ๋ถ€ํ•จ์ˆ˜ outer๋Š” ํ˜ธ์ถœ๋˜์–ด ๋‚ด๋ถ€ํ•จ์ˆ˜์ธ inner๋ฅผ test๋ณ€์ˆ˜์— returnํ•˜๊ณ  call stack์—์„œ ์ œ๊ฑฐ๋˜๊ฒŒ ๋œ๋‹ค. call stack์—์„œ ์ œ๊ฑฐ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— innerํ•จ์ˆ˜์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” outer ๋‚ด๋ถ€ ๋ณ€์ˆ˜ x์˜ ๊ฐ’์ด ์ •์ƒ์ ์œผ๋กœ ์ถœ๋ ฅ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ถœ๋ ฅ ๊ฒฐ๊ณผ x ๊ฐ’์ด ์ •์ƒ์ ์œผ๋กœ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ ํด๋กœ์ € ํ•จ์ˆ˜์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์œผ๋กœ ์™ธ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ ์ดํ›„์—๋„ ๋‚ด๋ถ€ ํ•จ์ˆ˜์ธinnerํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋˜์—ˆ์„ ๋•Œ์˜ ํ™˜๊ฒฝ์„ ๊ธฐ์–ตํ•˜์—ฌ ์ž์‹ ์˜ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„ ๋‚ด์˜ ๋ณ€์ˆ˜/ํ•จ์ˆ˜ ๋“ฑ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ์ด๋‹ค.

ํ•จ์ˆ˜์˜ ์Šค์ฝ”ํ”„๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๊ฐ€ ์•„๋‹Œ ์„ ์–ธํ•  ๋•Œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ฒฐ์ •๋˜๋Š”๋ฐ, ์ด๋ฅผ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ•‘(lexical scoping) ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋ฅผ debounce ์ฝ”๋“œ์— ์ ์šฉํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด๋ฉด,

function debounce(callback, delay) {
    let timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
            callback.apply(this, arguments)
        }, delay)
    }
}

debounce ๋‚ด๋ถ€์˜ ์ต๋ช…ํ•จ์ˆ˜๋Š” debounce ๋‚ด์—์„œ ์„ ์–ธ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ต๋ช…ํ•จ์ˆ˜์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋Š” debounce ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ต๋ช…ํ•จ์ˆ˜๋Š” ์ž์‹ ์ด ์†ํ•œ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„ ๋‚ด์˜ ๋ณ€์ˆ˜/ํ•จ์ˆ˜ ๋“ฑ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ๋˜๊ณ , ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ ๋˜์—ˆ์„ ๋‹น์‹œ๋ฅผ ๊ธฐ์–ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ ์ดํ›„์—๋„ ๋‚ด๋ถ€์˜ ์ต๋ช…ํ•จ์ˆ˜๋Š” timer ๋ณ€์ˆ˜์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

์ฝœ๋ฐฑํ•จ์ˆ˜

debounce ๋‚ด์˜ ํ•จ์ˆ˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ๋‚ด๋ถ€์—์„œ this ๋ฐ”์ธ๋”ฉ์„ ์œ„ํ•œ apply๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค. ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์ดํ•ด๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜ ํฌ์ŠคํŒ…์— ์ •๋ฆฌํ•ด๋‘์—ˆ๋‹ค.

* lodash

debounce์™€ throttle์„ ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ lodash๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.
lodash๋Š” ์„ฑ๋Šฅ์ด ๋ณด์žฅ๋œ ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์ฐธ๊ณ 
Debounce, Throttling
๋””๋ฐ”์šด์Šค(Debounce)์™€ ์Šค๋กœํ‹€(Throttle ) ๊ทธ๋ฆฌ๊ณ  ์ฐจ์ด์ 
ํด๋กœ์ €

profile
๐Ÿ‹ https://ye-yo.github.io/ ๋กœ ๋ธ”๋กœ๊ทธ ์ด์ „ํ–ˆ์Šต๋‹ˆ๋‹ค
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€