[Medium] ๐ Event Loop
1. Why Javascript need asynchronous ? And please explain callback and event loopโ
JavaScript์ ๋น๋๊ธฐ๊ฐ ํ์ํ ์ด์ ๋? ๊ทธ๋ฆฌ๊ณ callback๊ณผ event loop๋ฅผ ์ค๋ช ํด์ฃผ์ธ์
JavaScript๋ ๋ณธ์ง์ ์ผ๋ก ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด์ ๋๋ค. ๋ธ๋ผ์ฐ์ ์ DOM ๊ตฌ์กฐ๋ฅผ ์กฐ์ํ๋ ๊ฒ์ด ์ฃผ์ ์ญํ ์ค ํ๋์ธ๋ฐ, ๋ฉํฐ ์ค๋ ๋๋ก ๊ฐ์ ๋ ธ๋๋ฅผ ๋์์ ์์ ํ๋ฉด ์ํฉ์ด ๋งค์ฐ ๋ณต์กํด์ง๋ฏ๋ก ์ด๋ฅผ ํผํ๊ธฐ ์ํด ์ฑ๊ธ ์ค๋ ๋๋ฅผ ์ฑํํ์ต๋๋ค.
๋น๋๊ธฐ๋ ์ฑ๊ธ ์ค๋ ๋๋ผ๋ ๋ฐฐ๊ฒฝ์์์ ํด๊ฒฐ์ฑ ์ ๋๋ค. ํน์ ๋์์ด 2์ด์ ๋๊ธฐ๊ฐ ํ์ํ ๋, ๋ธ๋ผ์ฐ์ ๊ฐ 2์ด๋ฅผ ๊ธฐ๋ค๋ฆด ์๋ ์์ผ๋ฏ๋ก ๋ชจ๋ ๋๊ธฐ ์์ ์ ๋จผ์ ์คํํ๊ณ , ๋น๋๊ธฐ ์์ ์ task queue(์์ ๋๊ธฐ์ด)์ ๋ฃ์ด๋ก๋๋ค.
๋ธ๋ผ์ฐ์ ๊ฐ ๋๊ธฐ ์์ ์ ์คํํ๋ ํ๊ฒฝ์ call stack์ผ๋ก ์ดํดํ ์ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ๋จผ์ call stack ๋ด์ ์์ ์ ์์๋๋ก ์คํํ๊ณ , call stack์ด ๋น์ด์์์ ๊ฐ์งํ๋ฉด task queue์์ ๋๊ธฐ ์ค์ธ ์์ ์ call stack์ผ๋ก ์ฎ๊ฒจ ์์๋๋ก ์คํํฉ๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ call stack์ด ๋น์ด์๋์ง ํ์ธ => ์๋์ค => call stack ๋ด ์์ ๊ณ์ ์คํ
- ๋ธ๋ผ์ฐ์ ๊ฐ call stack์ด ๋น์ด์๋์ง ํ์ธ => ์ => task queue์ ๋๊ธฐ ์ค์ธ ์์ ์ด ์๋์ง ํ์ธ => ์์ => call stack์ผ๋ก ์ฎ๊ฒจ ์คํ
์ด๋ ๊ฒ ๋์์์ด ๋ฐ๋ณต๋๋ ๊ณผ์ ์ด event loop์ ๊ฐ๋ ์ ๋๋ค.
console.log(1);
// ์ด ๋น๋๊ธฐ ํจ์๊ฐ callback์
๋๋ค
setTimeout(function () {
console.log(2);
}, 0);
console.log(3);
// ์์๋๋ก 1 3 2๊ฐ ์ถ๋ ฅ๋จ
2. Why is setInterval not accurate in terms of timing ?โ
์
setInterval์ ํ์ด๋ฐ์ ์ ํํ์ง ์์๊ฐ?
-
JavaScript๊ฐ ์ฑ๊ธ ์ค๋ ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ด๋ฏ๋ก(ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์คํ ๊ฐ๋ฅ, ๋ค๋ฅธ ์์ ์ Queue์์ ๋๊ธฐ), setInterval์ callback ์คํ ์๊ฐ์ด ์ค์ ๋ ๊ฐ๊ฒฉ์ ์ด๊ณผํ๋ฉด ๋ค์ callback ์คํ์ด ์ง์ฐ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด 1์ด๋ง๋ค ํจ์๋ฅผ ์คํํ๋๋ก ์ค์ ํ์ง๋ง ํจ์ ๋ด์ 2์ด ๊ฑธ๋ฆฌ๋ ์์ ์ด ์๋ค๋ฉด ๋ค์ ์คํ์ 1์ด ์ง์ฐ๋ฉ๋๋ค. ๋์ ๋๋ฉด ์คํ ํ์ด๋ฐ์ด ์ ์ ๋ถ์ ํํด์ง๋๋ค.
-
๋ธ๋ผ์ฐ์ ๋ ์คํ ํ๊ฒฝ์ ์ ํ๋ ์์ต๋๋ค. ํ์ฌ ์ฃผ์ ๋ธ๋ผ์ฐ์ (Chrome, Firefox, Safari ๋ฑ)์ ์ต์ ๊ฐ๊ฒฉ ์๊ฐ์ ๋๋ต 4๋ฐ๋ฆฌ์ด์ ๋๋ค. 1๋ฐ๋ฆฌ์ด๋ง๋ค ์คํํ๋๋ก ์ค์ ํด๋ ์ค์ ๋ก๋ 4๋ฐ๋ฆฌ์ด๋ง๋ค ์คํ๋ฉ๋๋ค.
-
์์คํ ์ด ๋ฉ๋ชจ๋ฆฌ๋ CPU๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ ์์ ์ ์คํํ ๋๋ ์คํ ์๊ฐ ์ง์ฐ์ ์ ๋ฐํฉ๋๋ค. ์์ ํธ์ง์ด๋ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๊ฐ์ ์์ ์ ์ง์ฐ ๊ฐ๋ฅ์ฑ์ด ๋์์ง๋๋ค.
-
JavaScript์๋ Garbage Collection ๋ฉ์ปค๋์ฆ์ด ์์ด, setInterval ํจ์ ๋ด์์ ๋๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉ๋์ง ์์ผ๋ฉด GC์ ์ํด ํ์๋ฉ๋๋ค. ์ด ๋ํ ์คํ ์๊ฐ ์ง์ฐ์ ์์ธ์ด ๋ฉ๋๋ค.
๋์โ
requestAnimationFrameโ
ํ์ฌ setInterval์ ์ ๋๋ฉ์ด์
๊ตฌํ ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, requestAnimationFrame์ผ๋ก ๋์ฒด๋ฅผ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
- ๋ธ๋ผ์ฐ์ ๋ฆฌํ์ธํธ์ ๋๊ธฐํ: ๋ธ๋ผ์ฐ์ ๊ฐ ์ ํ๋ ์์ ๊ทธ๋ฆด ์ค๋น๊ฐ ๋์์ ๋ ์คํ๋ฉ๋๋ค. setInterval์ด๋ setTimeout์ผ๋ก ํ์ด๋ฐ์ ์ถ์ธกํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ์ ํํฉ๋๋ค.
- ์ฑ๋ฅ: ๋ธ๋ผ์ฐ์ ๋ฆฌํ์ธํธ์ ๋๊ธฐํ๋๋ฏ๋ก ๋ฆฌํ์ธํธ๊ฐ ํ์ ์์ ๋๋ ์คํ๋์ง ์์ต๋๋ค. ํญ์ด ๋นํ์ฑํ๋๊ฑฐ๋ ์ต์ํ๋ ๋ ํนํ ํจ๊ณผ์ ์ ๋๋ค.
- ์๋ ์ค๋กํ๋ง: ์ฅ์น์ ์ํฉ์ ๋ฐ๋ผ ์คํ ๋น๋๋ฅผ ์๋ ์กฐ์ ํ๋ฉฐ, ๋ณดํต ์ด๋น 60ํ๋ ์์ ๋๋ค.
- ๊ณ ์ ๋ฐ ์๊ฐ ๋งค๊ฐ๋ณ์: DOMHighResTimeStamp ํ์ ์ ๋ง์ดํฌ๋ก์ด ์ ๋ฐ๋ ์๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ ์ ์์ด, ์๊ฐ์ ๋ฏผ๊ฐํ ์์ ์ ๋ ์ ํํ๊ฒ ์ ์ดํ ์ ์์ต๋๋ค.
Exampleโ
let startPos = 0;
function moveElement(timestamp) {
// update DOM position
startPos += 5;
document.getElementById(
'myElement'
).style.transform = `translateX(${startPos}px)`;
// ์์๊ฐ ์์ง ๋ชฉ์ ์ง์ ๋๋ฌํ์ง ์์์ผ๋ฉด, ์ ๋๋ฉ์ด์
๊ณ์
if (startPos < 500) {
requestAnimationFrame(moveElement);
}
}
// start the animation
requestAnimationFrame(moveElement);
moveElement()์ ๊ฐ ํ๋ ์(๋ณดํต ์ด๋น 60ํ๋ ์)๋ง๋ค ์์์ ์์น๋ฅผ ์
๋ฐ์ดํธํ์ฌ 500 pixel์ ๋๋ฌํ ๋๊น์ง ๊ณ์ํฉ๋๋ค. ์ด ๋ฐฉ๋ฒ์ setInterval๋ณด๋ค ๋ ๋ถ๋๋ฝ๊ณ ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์
ํจ๊ณผ๋ฅผ ๊ตฌํํฉ๋๋ค.