๐ŸŒฟ

์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ์—๋Š” requestAnimationFrame!

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ requestAnimationFrame์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

2024.03.27

JavaScript Animation์„ ๊ตฌํ˜„ํ•  ๋•Œ, ๋‚˜๋„ ๋ชจ๋ฅด๊ฒŒ setTimeout์ด๋‚˜ setInterval๋กœ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ์ด ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธ€

JS๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ตฌํ˜„ ์‹œ ์ด์ „์—๋Š” setInterval๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ setInterval๋ณด๋‹ค requestAnimationFrame์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋” ์ ์ ˆํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๋‹ค.

์ตœ์ ํ™”๋œ ๋ชจ๋‹ฌ์„ ๊ตฌํ˜„ํ•˜๋ ค Toss์˜ useOverlay ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„๋ถ€๋ฅผ ์‚ด๋ณด๋‹ค๊ฐ€, requestAnimationFrame ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ˆ„๋ฝ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์จ์žˆ๋Š” ๊ฒƒ ์•„๋‹Œ๊ฐ€.

ํ† ์Šค์˜ OverlayController.tsx ์ค‘ ์ผ๋ถ€

  useEffect(() => {
    // NOTE: requestAnimationFrame์ด ์—†์œผ๋ฉด ๊ฐ€๋” Open ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
    requestAnimationFrame(() => {
      setIsOpenOverlay(true);
    });
  }, []);

๊ทธ ์ „์— ๋ช‡ ๋ฒˆ ์ด ํ•จ์ˆ˜๋ฅผ ๋ณธ ์ ์ด ์žˆ์–ด์„œ, ํ•ด๋‹น ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๋ณธ๊ฒฉ์ ์œผ๋กœ ์•Œ์•„๋ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.

requestAnimationFrame()

window.requestAnimationFrame()ย ๋ฉ”์„œ๋“œ๋Š” ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์•Œ๋ฆฌ๊ณ  ๋‹ค์Œ ๋ฆฌํŽ˜์ธํŠธ ๋ฐ”๋กœ ์ „์— ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์—…๋ฐ์ดํŠธํ•  ์ง€์ •๋œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์š”์ฒญํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌํŽ˜์ธํŠธ ์ด์ „์— ํ˜ธ์ถœํ•  ์ธ์ˆ˜๋กœ ์ฝœ๋ฐฑ์„ ๋ฐ›๋Š”๋‹ค.

๋ณดํ†ต ์›น ํŽ˜์ด์ง€์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ ๊ฐ„๋‹จํ•œ ๊ฒƒ์€ CSS์˜ ์†์„ฑ์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๊ณค ํ•˜์ง€๋งŒ, ๋น„๊ต์  ๋ณต์žกํ•œ (๋ธŒ๋ผ์šฐ์ €์˜ ๋†’์ด์— ๋”ฐ๋ฅธ ๋ณ€ํ™”๋ผ๋˜๊ฐ€,,) ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ ํ”„๋ ˆ์ž„์˜ ๋ˆ„๋ฝ์„ ์ตœ์†Œํ™”ํ•ด ์ž์—ฐ์Šค๋Ÿฌ์šด ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฒ˜๋ฆฌ์™€ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฒƒ์ด requestAnimationFrame() ์ด๋‹ค.

๋ธŒ๋ผ์šฐ์ €์˜ ํ”„๋ ˆ์ž„๊ณผ ์ฃผ์‚ฌ์œจ

ํ”„๋ ˆ์ž„๊ณผ ์ฃผ์‚ฌ์œจ์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ์•„๋ณด์ž. ์ฃผ์‚ฌ์œจ์ด๋ผ๋Š” ๊ฒƒ์€, 1์ดˆ ๋™์•ˆ ๋ชจ๋‹ˆํ„ฐ์˜ ํ™”๋ฉด ์ถœ๋ ฅ ๋นˆ๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด๋‹ค. ์˜ํ™”๋ฅผ ๋ณผ ๋•Œ, ํ™”๋ฉด์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์›€์ง์ด๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์‚ฌ์‹ค ์งง์€ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ์•ˆ์— ์ด์–ด์ง€๋Š” ์‚ฌ์ง„๋“ค์„ ์—ฐ์†ํ•ด์„œ ๋ณด๋Š” ๊ฒƒ์ด๋‹ค.

์ธ๊ฐ„์€ 1์ดˆ์— 60๋ฒˆ ์ด์ƒ์˜ ์‚ฌ์ง„๋“ค์ด ์—ฐ์†์ ์œผ๋กœ ๋ณด์—ฌ์•ผ ์ž์—ฐ์Šค๋Ÿฌ์šด ์˜์ƒ์ด๋ผ๊ณ  ๋Š๋‚€๋‹ค. ์ฆ‰ 60FPS์ด ์ƒ์ด ๋˜์–ด์•ผ ์ž์—ฐ์Šค๋Ÿฝ๋‹ค๊ณ  ์—ฌ๊ธด๋‹ค

ํ”„๋ ˆ์ž„ ๋น„๊ต ์˜์ƒ

๋”ฐ๋ผ์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ถ€๋“œ๋Ÿฌ์šด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด, 1000ms / 60fps = 16.6ms ๋งˆ๋‹ค ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

ํƒ€์ด๋จธ ํ•จ์ˆ˜์™€์˜ ์ฐจ์ด์ 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” setTimeout๊ณผ setInterval์ด ์žˆ๋‹ค.

์• ๋‹ˆ๋ฉ”์ด์…˜์„ setInterval ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

const performAnimation = () => {
	setInterval(performAnimation, 1000 / 60)
}

๊ทธ๋Ÿฐ๋ฐ ์™œ requestAnimationFrame ์„ ์‚ฌ์šฉํ•˜๋ผ๋Š” ๊ฒƒ์ผ๊นŒ?

ํ•ด๋‹น ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ ์€, ์šฐ๋ฆฌ๊ฐ€ ์ •ํ™•ํ•œ ์‹œ๊ฐ„์— ์ •ํ™•ํ•˜๊ฒŒ ํ•จ์ˆ ์„ ์‹คํ–‰์‹œ์ผฐ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค๋ฅธ ์ž‘์—…๋•Œ๋ฌธ์— ๋ฐ”์˜๊ฑฐ๋‚˜ setTimeout ํ•จ์ˆ˜๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ repaint ์‹œ์ ์— ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ์‚ฌ์ดํด๋กœ ๋ฐ€๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‹ค์Œ ์‚ฌ์ดํด(๋‹ค์Œ ๋ฆฌํŽ˜์ธํŠธ ์‹œ์ )๋กœ ๋ฐ€๋ฆฐ๋‹ค๋Š” ๊ฒƒ์€ ์ฆ‰, ํ•œ ํ”„๋ ˆ์ž„์ด ๋ˆ„๋ฝ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์•„๋ž˜๋Š” setTimeout, setInterval์˜ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ์ผ์–ด๋‚˜๋Š” ์ผ์„ ๋ณด์—ฌ์ค€๋‹ค.

paint - ์ดˆ๋ก render - ๋ณด๋ผ javascript - ๋…ธ๋ž‘

16.6ms์˜ ํƒ€์ด๋ฐ๊ณผ ๊ด€๊ณ„ ์—†์ด JS์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฃผ์‚ฌ์œจ๊ณผ ๊ด€๊ณ„ ์—†์ด ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ๋•Œ๋„ ์žˆ๊ณ , JS์ฝ”๋“œ๊ฐ€ ๋ ˆ์ด์•„์›ƒ - ํŽ˜์ธํŠธ ๊ณผ์ • ์ „์— ๋๋‚˜์ง€ ์•Š์œผ๋ฉด ๋ ˆ์ด์•„์›ƒ- ํŽ˜์ธํŠธ ๊ณผ์ •๋„ ๋ฐ€๋ฆฌ๊ฒŒ ๋˜๊ธฐ๋„ ํ•œ๋‹ค.

setTimeout, setInterval

๋˜ํ•œ ํ˜ธ์ถœ์ด ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์‚ฌ์œจ ๋ณด๋‹ค ๋งŽ์ด ๋  ๋•Œ์—๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋Š๊ธฐ๋Š” ๋Š๋‚Œ์„ ์ค€๋‹ค.

๊ฐ„๋‹จํžˆ ์ƒ๊ฐํ•˜๋ฉด 4๊ฐœ์˜ ์‚ฌ์ง„์ด ํ˜ธ์ถœ๋˜๋Š”๋ฐ ๋งˆ์ง€๋ง‰ ์‚ฌ์ง„๋งŒ ๋‹ด๊ธฐ๊ฒŒ ๋˜๊ณ , ๋”ฐ๋ผ์„œ 3๊ฐœ์˜ ํ”„๋ ˆ์ž„์€ ๋ˆ„๋ฝ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ํ˜ธ์ถœ์ด ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์‚ฌ์œจ ๋ณด๋‹ค ๋งŽ์ด ๋  ๋•Œ

requestAnimationFrame์˜ ์ด์ 

ํ”„๋ ˆ์ž„ ์ฃผ๊ธฐ์— ๋งž์ถฐ ์‹คํ–‰๋œ๋‹ค

requestAnimationFrame์€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฝ”๋“œ๊ฐ€ rendering๊ณผ painting ์ด๋ฒคํŠธ ์ „์— ์‹คํ–‰๋œ๋‹ค. ์‹ค์ œ ํ™”๋ฉด์ด ๊ฐฑ์‹ ๋˜์–ด์„œ ํ‘œ์‹œ๋˜๋Š” ์ฃผ๊ธฐ์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ  ๋ˆ„๋ฝ์ด ์ตœ์†Œํ™”๋œ๋‹ค.

requestAnimationFrame

๋ณ„๋„์˜ Animation Queue์— ์ €์žฅ๋œ๋‹ค

๋˜ํ•œ SetTimeout๊ณผ SetInterval์„ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” Task Queue์— ์ €์žฅ๋˜๋Š”๋ฐ, AnimationRequestFrame์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ„๋„์˜ Animation Queue์— ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— Promise์ด์™ธ์˜ ๋‹ค๋ฅธ ๋น„๋™๊ธฐ ์ž‘์—…(Micro task Queue)์— ๋น„ํ•ด ๋ฐ€๋ฆด ์œ„ํ—˜์ด ์ ๋‹ค.

๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋™์ž‘์ด ๋ฉˆ์ถ˜๋‹ค

๋ธŒ๋ผ์šฐ์ €์˜ ์ฐฝ์„ ์ˆจ๊ธฐ๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์ฐฝ์„ ๋ณผ ๋•Œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ถˆํ•„์š”ํ•œ ์ „๋ ฅ์„ ์†Œ๋ชจํ•˜์ง€ ์•Š๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์˜ํ•ด์„œ ์ผ์‹œ์ค‘์ง€๋œ๋‹ค.

ํ˜ธ์ถœ ํšŸ์ˆ˜๊ฐ€ ์ž๋™์ ์œผ๋กœ ๋””์Šคํ”Œ๋ ˆ์ด์˜ ์ฃผ์‚ฌ์œจ์— ๋งž์ถฐ์ง„๋‹ค

ํ˜ธ์ถœ ์‹œ๊ฐ„์„ ์ˆ˜๋™์œผ๋กœ ์ •ํ•ด์ค˜์•ผ ํ–ˆ๋˜ setTimeout๊ณผ setInterval๊ณผ ๋‹ฌ๋ฆฌ, ํ˜„์žฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋””์Šคํ”Œ๋ ˆ์ด์˜ ์ฃผ์‚ฌ์œจ์— ๋งž์ถฐ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ž๋™์œผ๋กœ ์‹คํ–‰์‹œํ‚จ๋‹ค. ์ด๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€, 60fps์ธ ๋””์Šคํ”Œ๋ ˆ์ด ๋ณด๋‹ค 120fps์˜ ์ฃผ์‚ฌ์œจ์„ ๊ฐ€์ง„ ๋””์Šคํ”Œ๋ ˆ์ด์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

๋”ฐ๋ผ์„œ ํ•ญ์ƒ ํ”„๋ ˆ์ž„์—์„œ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ง„ํ–‰๋  ๊ฒƒ์ธ์ง€ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜(ํ˜น์€ ํ˜„์žฌ ์‹œ๊ฐ„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๋ช‡๋ช‡ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ)๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค

์‚ฌ์šฉ๋ฒ•

requestAnimationFrame์‚ฌ์šฉ๋ฒ•์€ setTimeout์ฒ˜๋Ÿผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ถœ๋ ฅํ•  ๋•Œ ๋งˆ๋‹ค requestAnimationFrame์— ๋“ฑ๋ก๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋“ค์„ ๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœํ•œ๋‹ค.

const performAnimation = () => {
  requestAnimationFrame(performAnimation) 
}

requestAnimationFrame(performAnimation);

์ทจ์†Œํ•˜๋ ค๋ฉด cancelAnimationFrame ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์—๋‹ˆ๋ฉ”์ด์…˜์„ ์ทจ์†Œํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด ๊ผญ ์ทจ์†Œํ•ด์ค˜์•ผ ํ•œ๋‹ค.

const performAnimation = () => {
	if(์กฐ๊ฑด){
		cancelAnimationFrame(performAnimation);
		return;
	}
	requestAnimationFrame(performAnimation);
}
requestAnimationFrame(performAnimation);

requestAnimationFrame์˜ ์ฝœ๋ฐฑ Function์—๋Š” ํ•œ ๊ฐ€์ง ์ธ์ž๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด ์ธ์ž๋Š” timestamp์ด๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹คํ–‰๋œ ์ดํ›„์˜ ์‹œ๊ฐ„์„ ๋ฆฌํ„ดํ•œ๋‹ค.

const performAnimation = (timestamp: DOMHighResTimeStamp) => {
  requestAnimationFrame(performAnimation) 
  
}

requestAnimationFrame(performAnimation);

ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” requestAnimationFrame callback Function์— ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ์ฃผ๊ณ  ์‹ถ์—ˆ๋‹ค. requestAnimationFrame์€ ์ž๋™์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ € ์ฃผ์‚ฌ์œจ์— ๋งž์ถฐ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—, 50ms ์™€ ๊ฐ™์€ ํŠน์ • ๊ฐ’์„ ์ฃผ์ง€ ๋ชปํ•œ๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด useAnimationFrame ํ›…์„ ๋งŒ๋“ค๊ณ , ์‹œ๊ฐ„ ์ž…๋ ฅ ์‹œ ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ์žฌ์„œ callbackFn์ด ์‹คํ–‰๋˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

import {useEffect, useRef, useState} from 'react'


import {useEffect, useRef} from 'react'

const useRequestAnimationFrame = (callbackFn: () => boolean, ms?: number) => {
  const idRef = useRef<number | null>(null)
  const startTimeRef = useRef<number | null>(null)

  useEffect(() => {
    const animationFn = (timestamp: DOMHighResTimeStamp) => {
      // for throttle
      if (!startTimeRef.current) {
        startTimeRef.current = timestamp
      }
      const elapsed = timestamp - startTimeRef.current

      if (!ms || elapsed >= ms) {
        const isNext = callbackFn()
        startTimeRef.current = timestamp

        // if isNext is false, cancel the animation
        if (!isNext) {
          cancelAnimationFrame(idRef.current!)
          return
        }
      }

      requestAnimationFrame(animationFn)
    }

    idRef.current = requestAnimationFrame(animationFn)

    return () => {
      if (idRef.current) cancelAnimationFrame(idRef.current)
    }
  }, [callbackFn, ms])

  return idRef.current
}

export default useRequestAnimationFrame


์ด๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€, ์ •ํ™•ํ•˜๊ฒŒ 50ms๋งˆ๋‹ค ๋ถˆ๋Ÿฌ์ง€๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ๋Š” ์ ์ด๋‹ค. ์‹คํ–‰ ๊ฒฐ๊ณผ ํƒ€์ž„์Šคํƒฌํ”„ ์œ„์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ ์ฃผ์‚ฌ์œจ์— ๋งž์ถฐ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์—,

๋‚ด ์ปดํ“จํ„ฐ (60fps) ๊ธฐ์ค€์œผ๋กœ 16.6 * 3 ์ด๋ฉด ๊ฑฐ์˜ 50ms์ด๋‹ค.

๊ทธ๋ž˜์„œ 50ms ๊ธฐ์ค€ 3๋ฒˆ ~ 4๋ฒˆ์งธ ํ˜ธ์ถœ ๋งˆ๋‹ค ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ์‹คํ–‰ ์‹œ๊ฐ„์€ 50ms ~ 66ms(50ms + 16ms)์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

@ 2025. nyoung all rights reserved