What the heck is the event loop anyway? | Philip Roberts | JSConf EU - hochan222/Everything-in-JavaScript GitHub Wiki
How does JavaScript even work?
v8?? chrome runtime??? ๋ค์ด๋ ๋ดค์ง๋ง ์์ธํ๋ ๋ชจ๋ฅธ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ๋ฌผ์ด๋ณธ๋ค.
What is Javascript?
A single-threaded, non-blocking, asynchronous, concurrent language. It have call stack, an event loop, a callback queue some other apis and stuff.
๋ผ๊ณ ์๋ ์์ด ๋ค์ด๋ดค์ง๋ง ์ฌ์ ํ ๊ทธ ์๋ฏธ๋ฅผ ์ ํํ ๋ชจ๋ฅธ๋ค.
V8์ cloneํด์ ์ฐพ์๋ณด์๋๋ setTimeout ์ด๋ DOM, HTTP Request๋ฅผ ๊ด๋ฆฌํ๋ ์ฝ๋๋ค์ ์ฐพ์ ๋ณผ ์ ์์๋ค.
๋ค์์ ๊ฐ๋ตํ๋ Javascript Runtime ๊ตฌ์กฐ์ด๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ฐ๋ ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ด๋ค. ์ฑ๊ธ ์ฐ๋ ๋ ๋ฐํ์์ ๊ฐ์ง๊ณ ์๋ค๋ ๋ป์ธ๋ฐ, ๊ฒฐ๊ตญ ํ๋ฒ์ ํ๋์ ์ฑ๊ธ ์ฝ ์คํ๋ง ๊ฐ์ง ์ ์์์ ์๋ฏธํ๋ค. (== ํ๋์ ํ๋ก๊ทธ๋จ์ ๋์์ ํ๋์ ์ฝ๋๋ง ์คํ ํ ์ ์๋ค.)
Call Stack์ ์๋ฃ๊ตฌ์กฐ๋ก ์คํ๋๋ ์์๋ฅผ ๊ธฐ์ตํ๊ณ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์คํ์ ๊ฐ์ฅ ์์ชฝ์์ ํด๋น ํจ์๋ฅผ ๊บผ๋ด๊ฒ ๋๋๋ฐ ์ด๊ฒ ์ฝ ์คํ์ด ํ๋ ์ผ์ ์ ๋ถ์ด๋ค.
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด
- ์คํ๋๋ ์ฝ๋ ์์ฒด๋ฅผ ์๋ฏธํ๋ main ํจ์๋ฅผ ์คํ์ ์ง์ด ๋ฃ๊ฒ ๋๋ค.
- ํจ์๋ฅผ ์ ์ํ๊ฒ ๋๋ค.
- ๋ง์ง๋ง์ printSquare(4)๋ฅผ ๋ง๋๊ณ ํจ์ ํธ์ถ์ด๋, ์คํ์ ํจ์๋ฅผ ์ถ๊ฐํ๋ค.
- ํธ์ถ๋๋ ํจ์๋ค์ stack์ ๋ฃ๊ณ ๋ฌด์์ธ๊ฐ return ํ ๋๋ง๋ค ์คํ ๋งจ์์์๋๊ฒ์ ๊บผ๋ด๊ฒ ๋๋ค.
- printSquare๋ return์ด ์์ง๋ง ์๋ฌต์ ์ผ๋ก return ํ๋ค.
๋ง์ฝ ์์ ๊ฒฝ์ฐ ์๋ฌ๊ฐ ๋๋ค๋ฉด ํฌ๋กฌ ๊ฐ๋ฐ์ ๋๊ตฌ์์ ์คํ์ ๊ผฌ๋ฆฌ๋ฅผ ๋ฌผ๋ฉด์ Oops!๋ฅผ ํ์ํ ๊ฒ์ด๋ค. ์ ์ ์ฌ๋ผ๊ฐ๋ค๊ฐ ์ต๋ช ํจ์(=mainํจ์)๊น์ง ์ฌ๋ผ๊ฐ๋ค!
blocking
๋ธ๋กํน์ ์ ํํ ์ ์๋ ์กด์ฌํ์ง ์๋๋ค. ๊ทธ์ ๋๋ฆฌ๊ฒ ๋์ํ๋ ์ฝ๋ ์ผ ๋ฟ์ด๋ค.
console.log๋ ๋๋ฆฌ์ง ์์ง๋ง ์ฌ๋ฌ๋ฒ while๋ฌธ์ผ๋ก ํธ์ถ๋๋ฉด ๋๋ฆด๊ฒ์ด๋ค.
๋คํธ์ํฌ ์์ฒญ์ด๋ ์ด๋ฏธ์ง ํ๋ก์ธ์ฑ์ ๋๋ฆฌ๋ค. ๋๋ฆฐ ๋์์ด ์คํ์ ๋จ์์๋ ๊ฒ์ ๋ณดํต ๋ธ๋กํน์ด๋ผ๊ณ ํ๋ค.
var foo = $.getSync('//foo.com');
var bar = $.getSync('//bar.com');
var qux = $.getSync('//qux.com');
console.log(foo);
console.log(bar);
console.log(qux);
์ ์ฝ๋์ alert๋ฒํผํ๊ณ ๋ฐ์ a href ํ๊ทธ๊ฐ ์๋ค๊ณ ์น์.
์ฐ๋ฆฌ๋ alert๋ฒํผ์ ๋๋ฌ๋ ์ ์์ฒญ ์๋ต์ด ๋๋ ๋ ๊น์ง alert ๋ฉ์ธ์ง ์ฐฝ์ด ๋จ์ง ์์๊ฒ์ด๋ค.
๋ํ, a href ํ๊ทธ ๋ํ ๋์ํ์ง ์๋๋ค.
๋ธ๋ผ์ฐ์ ๋ ๋ชจ๋ ๋ฆฌํ์คํธ๊ฐ ์๋ฃ๋ ๋ ๊น์ง ๋ฉ์ถฐ์์ ๊ฒ์ด๋ค.
๋ฉ์ถฐ์๋๋์ ํ๋์ ๊ธฐ์ตํ๊ณ ์์ง๋ง ๋ ๋๋ง ํ ์ ์๋ค.
the solution?
asynchronous callbacks
๋ธ๋ผ์ฐ์ ๋ node.js์๋ ๋ธ๋กํนํจ์๊ฐ ๊ฑฐ์ ์๋ค. ๋๋ถ๋ถ ๋น๋๊ธฐ๋ก ๋ง๋ค์ด์ก๋ค. ์ด๋ค ์ฝ๋๋ฅผ ์คํํ๋ฉด ๊ฒฐ๊ตญ ์ฝ๋ฐฑ์ ๋ฐ๊ณ ๋์ค์ ์คํํ๋๊ฒ์ ์๋ฏธํ๋ค.
settimeoutํจ์๋ฅผ ์คํ์ํฌ ๋ Call Stack์๋ ์ถ๊ฐ๊ฐ ๋์ง๋ง ์ฌ๋ผ์ก๋ค๊ฐ ์ค์ ํ ์๊ฐ ์ดํ์ ๋ค์ ์คํ ๋ ๊ฒ์ด๋ค.
Concurrency & the Event Loop
์ด๋ฒคํธ ๋ฃจํ์ ๋์์ฑ์ด ์ด ์ญํ ์ ํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ๋์์ ํ๊ฐ์ง ์ผ ๋ฐ์ ํ์ง ๋ชปํ๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ด ์ฌ๋ฌ ์ผ๋ค์ ๋์์ ํ ์ ์๋ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ๋ ๋จ์ ๋ฐํ์ ์ด์์ ์๋ฏธํ๊ธฐ ๋๋ฌธ์ด๋ค.
Call Stack์์ setTimeout์ webapis์ ์ถ๊ฐ์ํจ ํ popํ๋ค.
webapis๋ ๋ฐ๋ก Call Stack์ ์ถ๊ฐํ ์ ์๊ธฐ ๋๋ฌธ์ task queue์ ์ง์ด๋ฃ์ด์ง๋ค.
์ด๋ฒคํธ ๋ฃจํ์ ๋ค๋ฌ์๋ค.
์ด๋ฒคํธ ๋ฃจํ๋ ์ด ์ ์ฒด ์์คํ
์์ ์์ฃผ ๋จ์ํ ์ผ์ ํ๋ ์์ ํํธ์ด๋ค.
์ด๋ฒคํธ ๋ฃจํ์ ์ญํ ์ ์ฝ ์คํ๊ณผ ํ
์คํฌ ํ๋ฅผ ์ฃผ์ํ๋ ๊ฒ์ด๋ค.
์คํ์ด ๋น์ด์์ผ๋ฉด, ํ์ ์ฒซ๋ฒ์งธ ์ฝ๋ฐฑ์ ์คํ์ ์์ ํจ๊ณผ์ ์ผ๋ก ์คํ ํ ์ ์๊ฒ ํด์ค๋ค.
์คํ์ด ๋น์ด์์๋ ์ด๋ฒคํธ ๋ฃจํ๋ ์ฝ๋ฐฑ์ ์คํ์ ๋ฃ์ด์ค๋ค.
Stack์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ญ์ด๋ค. V8์์ง์์ ์ด์ console.log("there")์ ์คํํ๋ค.
// Synchronous
[1, 2, 3, 4].forEach(function (i) {
console.log('processing sync')
delay();
});
// Asynchronous
function asyncForEach(array, cb) {
array.forEach(function () {
setTimeout(cb, 0);
})
}
asyncForEach([1, 2, 3, 4], function (i) {
console.log('processing async', i);
delay();
})
๋๊ฐ์ง ํจ์์ ์ฐจ์ด๋ ๋๊ธฐ๋ Stack์์ญ์์๋ง ์คํ๋๋ค๋ ๊ฒ์ด๊ณ ๋น๋๊ธฐ๋ Task Queue์ ์์๋ค๊ฐ Stack์์ญ์ด ๋น์์ง๋ฉด ์คํ๋๋ค๋๊ฒ์ด๋ค.
๋ฐ๋ผ์, ์์ฃผ ํฐ ๋ฐฐ์ด ์์ ์ ํ ๋, ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๊ฒ ๋๋ฉด ๋ค๋ฅธ ์์ ์ ์งํํ์ง ๋ชปํ ์ ์์ด์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋๊ฒ์ด ์ด์์ ์ด๋ค.
๋ ๋ ๋ํ ๋ง์ฐฌ๊ฐ์ง์ธ๋ฐ ๋ ๋๋ง๋ ์คํ์ด ๋น์์ง ๋ ๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ์คํ๋๋ค.
๋ค๋ฅธ ์ ์ด๋ผ๋ฉด ๋ ๋๋ ์ฝ๋ฐฑ์ ๋นํด ๋ ๋์ ์ฐ์ ์์๋ฅผ ๊ฐ๋๋ค.
์คํ์ ๋๋ฆฐ ์์ ์ ๋ฃ์ด์ ๋ธ๋ผ์ฐ์ ๊ฐ ํ ์ผ์ ๋ชปํ๊ฒ ํ์ง ๋ง์๋ผ, ์ ๋์ ์ธ UI๋ฅผ ๋ง๋ค์ด๋ผ.
๊ทธ ์์๋ก ์คํฌ๋กค ์ด๋ฒคํธ๋กค ๋ฑ๋กํ ๋, ์์ฒญ๋ ์ด๋ฒคํธ๋ค์ด Callback Queue์ ์์ด๊ฒ ๋ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๋ ์ผ์ ์ด์ ํ
์ ๋๊ณ ์คํํ๋ฏ๋ก์จ ์ด๋ฒคํธ ๋ฒ๋์ ๋ฐฉ์ง ํ ์ ์๋ค.