
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ Deep Dive ๋์์ 41์ฅ ํ์ด๋จธ๋ฅผ ์ ๋ฆฌํ์์ต๋๋ค.
ํจ์๋ฅผ ๋ช ์์ ์ผ๋ก ํธ์ถํ์ง ์๊ณ ์ผ์  ์๊ฐ์ด ๊ฒฝ๊ณผ๋ ์ดํ์ ํธ์ถ๋๋๋ก ํจ์ ํธ์ถ์ ์์ฝํ๋ ค๋ฉด ํ์ด๋จธ ํจ์๋ฅผ ์ฌ์ฉํ๋ค. ์ด๋ฅผ ํธ์ถ ์ค์ผ์ค๋ง์ด๋ผ ํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ํ์ด๋จธ๋ฅผ ์์ฑํ  ์ ์๋ ํ์ด๋จธ ํจ์ setTImeout๊ณผ setInterval, ํ์ด๋จธ๋ฅผ ์ ๊ฑฐํ  ์ ์๋ ํ์ด๋จธ ํจ์ clearTimeout๊ณผ clearInterval์ ์ ๊ณตํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ฑ๊ธ ์ค๋ ๋๋ก ๋์ํ๊ณ  ๋จ ํ๋์ ์คํ ์ปจํ
์คํธ ์คํ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ ๊ฐ์ง ์ด์์ ํ์คํฌ๋ฅผ ๋์์ ์คํํ  ์ ์๋ค. ์ด๋ฐ ์ด์ ๋ก setTImeout๊ณผ setInterval์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
setTimeoutํจ์๋ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์๊ฐ์ผ๋ก ๋จ ํ ๋ฒ ๋์ํ๋ ํ์ด๋จธ๋ฅผ ์์ฑํ๋ค. ์ดํ ํ์ด๋จธ๊ฐ ๋ง๋ฃ๋๋ฉด ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋ฐ์ ์ฝ๋ฐฑ ํจ์๊ฐ ํธ์ถ๋๋ค. ์ฆ, setTimeout ํจ์์ ์ฝ๋ฐฑ ํจ์๋ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์๊ฐ ์ดํ ๋จ ํ ๋ฒ ์คํ๋๋๋ก ํธ์ถ ์ค์ผ์ค๋ง๋๋ค.
// setTimeout ํจ์๋ ์์ฑ๋ ํ์ด๋จธ๋ฅผ ์๋ณํ  ์ ์๋ ๊ณ ์ ํ ํ์ด๋จธ id๋ฅผ ๋ฐํํ๋ค.
const timerId = setTimeout(() => console.log('Hi!'), 1000);
// ํ์ด๋จธ id๋ฅผ clearTimeout ํจ์์ ์ธ์๋ก ใ
ใ
ใด๋ฌํ์ฌ ํ์ด๋จธ๋ฅผ ์ทจ์ํ๋ค.
clearTimeout(timerId)
`setInterval ํจ์๋ ๋ ๋ฒ์จฐ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์๊ฐ์ผ๋ก ๋ฐ๋ณต ๋์ํ๋ ํ์ด๋จธ๋ฅผ ์์ฑํ๋ค. ์ดํ ํ์ด๋จธ๊ฐ ๋ง๋ฃ๋  ๋๋ง๋ค ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ํจ์๊ฐ ๋ฐ๋ณต ํธ์ถ๋๋ค. ์ด๋ ํ์ด๋จธ๊ฐ ์ทจ์๋ ๋๊น์ง ๊ณ์๋๋ค!
let count = 1
const timeoutId = sestInterval(() => {
  console.log(count) // 1 2 3 4 5
  
  // count๊ฐ 5์ด๋ฉด ํ์ด๋จธ๋ฅผ ์ทจ์ํ๋ค.
  if(count++ === 5) clearInterval(timeoutId)
}, 1000)
๋๋ฐ์ด์ค์ ์ค๋กํ์ ์งง์ ์๊ฐ ๊ฐ๊ฒฉ์ผ๋ก ์ฐ์ํด์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ๊ทธ๋ฃนํํด์ ๊ณผ๋ํ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํธ์ถ์ ๋ฐฉ์งํ๋ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ด๋ค.
๋๋ฐ์ด์ค๋ ์งง์ ์๊ฐ ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ๊ทธ๋ฃนํํด์ ๋ง์ง๋ง์ ํ ๋ฒ๋ง ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํธ์ถ๋๋๋ก ํ๋ค.
const $input = document.querySelector('input')
const $msg = document.querySelector('.msg')
const debounce = (callback, delay) => {
  let timerId
  
  // debounce ํจ์๋ timerId๋ฅผ ๊ธฐ์ตํ๋ ํด๋ก์ ๋ฅผ ๋ฐํํ๋ค.
  return event => {
    // delay๊ฐ ๊ฒฝ๊ณผํ๊ธฐ ์ด์ ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์ด์  ํ์ด๋จธ๋ฅผ ์ทจ์ํ๊ณ  ์๋ก์ด ํ์ด๋จธ๋ฅผ ์ฌ์ค์ ํ๋ค.
    if (timerId) clearTimeout(timerId)
    timerId = setTimeout(callback, delay, event)
  }
}
// debounce ํจ์๊ฐ ๋ฐํํ๋ ํด๋ก์ ๊ฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ๋ฑ๋ก๋๋ค.
// 300ms ๋์ input ์ด๋ฒคํธ๊ฐ ๋ ์ด์ ๋ฐ์ํ์ง ์์ผ๋ฉด ํ ๋ฒ๋ง ํธ์ถ๋๋ค.
$input.oninput = debounce(e => {
  $msg.textContent = e.target.value
}, 300)
์ค๋กํ์ ์งค์ ์๊ฐ ๊ฐ๊ฒฉ์ผ๋ก ์ฐ์ํด์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ๊ทธ๋ฃนํํด์ ์ผ์  ์๊ฐ ๋จ์๋ก ์ด๋ฒคํธ๊ฐ ํธ์ถ๋๋๋ก ํธ์ถ ์ฃผ๊ธฐ๋ฅผ ๋ง๋ ๋ค.
const throttle = (callback, delay) => {
  let timerId
  
  // throttle ํจ์๋ timerId๋ฅผ ๊ธฐ์ตํ๋ ํด๋ก์ ๋ฅผ ๋ฐํํ๋ค.
  return event => {
    // delay๊ฐ ๊ฒฝ๊ณผํ๊ธฐ ์ด์ ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์๋ฌด๊ฒ๋ ํ์ง ์๋ค๊ฐ delay๊ฐ ๊ฒฝ๊ณผํ์ ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์๋ก์ด ํ์ด๋จธ๋ฅผ ์ฌ์ค์ ํ๋ค.
    // ๋ฐ๋ผ์ delay ๊ฐ๊ฒฉ์ผ๋ก callback์ด ํธ์ถ๋๋ค.
    if(timerId) return
    timerId = setTimeout(() => {
      callback(event)
      timerId = null
    }, delay, event)
  }
}
์ด๋ฐ ์ค๋กํ์ ๋ฌดํ ์คํฌ๋กค UI ๊ตฌํ ๋๋ scroll ์ด๋ฒคํธ ์ฒ๋ฆฌ์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค.
Ref
- ์ด์ ๋ชจ ์ , โ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ Deep Diveโ, ์ํค๋ถ์ค
 - setTimeout๊ณผ setInterval์ ์ด์ฉํ ํธ์ถ ์ค์ผ์ค๋ง