๐ ์๋ฐ์คํฌ๋ฆฝํธ ์ด๋ฒคํธ ๋ฃจํ ๋์ ๊ตฌ์กฐ & ์๋ฆฌ ๋ํ์
์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ์ ์ด๋ฒคํธ ๋ฃจํ
๋ธ๋ผ์ฐ์ ์ ๋ฉํฐ ์ค๋ ๋๋ก ์์ ์ ๋์์
Javascript๋ ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด๋ผ๊ณ ๋ค์ด๋ณธ ์ ์ด ์์ ๊ฒ์ด๋ค. '์ฑ๊ธ' ์ค๋ ๋๋ผ ํ ๋ฒ์ ํ๋์ ์์ ๋ง ์ํ์ด ๊ฐ๋ฅํ๋ค. ๋ฐ๋ฉด Java ๋ Python์ ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ง์ํ์ฌ ์ํ๋ ์ฝ๋ ๋ก์ง์ ๋์์ ์ํ ์ํค๋ ๋ฉํฐ ์์ ์ด ๊ฐ๋ฅํ๋ค.
๊ทธ๋ฐ๋ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋คํธ์ํฌ ์์ฒญ์ด๋ ์ด๋ฒคํธ ์ฒ๋ฆฌ, ํ์ด๋จธ์ ๊ฐ์ ์์ ์ ๋ฉํฐ๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ๋ง์ผ ์ฑ๊ธ ์ค๋ ๋๋ก ๋ธ๋ผ์ฐ์ ๋์์ด ํ๋ฒ์ ํ๋์ฉ ์ํํ๊ฒ ๋๋ฉด, ์ฐ๋ฆฌ๊ฐ ํ์ผ์ ๋ค์ด๋ก๋ ๋ฐ์ ๋์ ๋ธ๋ผ์ฐ์ ๋ ํ์ผ์ ๋ค ๋ฐ์ ๋๊น์ง ์น์ํ๋ ๋ชปํ๊ณ ๋ฉ์ถฐ ๋๊ธฐํด์ผ ํ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ํ์ผ ๋ค์ด, ๋คํธ์ํฌ ์์ฒญ, ํ์ด๋จธ, ์ ๋๋ฉ์ด์ ์ด๋ฌํ ์ค๋ ๊ฑธ๋ฆฌ๊ณ ๋ฐ๋ณต์ ์ธ ์์ ๋ค์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์๋ ๋ธ๋ผ์ฐ์ ๋ด๋ถ์ ๋ฉํฐ ์ค๋ ๋์ธ Web APIs์์ ๋น๋๊ธฐ + ๋ ผ๋ธ๋กํน์ผ๋ก ์ฒ๋ฆฌ๋๋ค. ๋น๋๊ธฐ + ๋ ผ๋ธ๋กํน(Async + Non blocking)๋ ๋ฉ์ธ ์ค๋ ๋๊ฐ ์์ ์ ๋ค๋ฅธ ๊ณณ์ ์์ฒญํ์ฌ ๋์ ์คํํ๊ณ , ๊ทธ ์์ ์ด ์๋ฃ๋๋ฉด ์ด๋ฒคํธ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์คํํ๋ ๋ฐฉ์์ ๋งํ๋ค. (์ฝ๊ฒ ๋งํด ํ์ผ ๋ค์ด๋ก๋ ์์ฒญ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ ์ผ๋ก ์ ์ดํ์ฌ ๋์์ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋๋ก ํ ๊ฒ์ผ๋ก ์ดํดํ๋ฉด ๋๋ค)
์ฆ, ๋น๋๊ธฐ๋ก ๋์ํ๋ ํต์ฌ์์๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด๊ฐ ์๋๋ผ ๋ธ๋ผ์ฐ์ ๋ผ๋ ์ํํธ์จ์ด๊ฐ ๊ฐ์ง๊ณ ์๋ค๊ณ ๋ณด๋ฉด ๋๋ค. Node.js ์์๋ libuv ๋ด์ฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ฒ๋ฆฌํ๋ค.
์ด๋ฒคํธ ๋ฃจํ๋ ๋ธ๋ผ์ฐ์ ๋์์ ์ ์ดํ๋ ๊ด๋ฆฌ์
์ฑ๊ธ ์ค๋ ๋์ธ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ ์ ๋ฉํฐ ์ค๋ ๋๋ก ๋๋ ค ์์ ์ ๋์์ ์ฒ๋ฆฌ์ํค๊ฒ ํ๋๊ฐ, ๋๋ ์ฌ๋ฌ ์์ ์ค ์ด๋ค ์์ ์ ์ฐ์ ์ผ๋ก ๋์์ํฌ ๊ฒ์ธ์ง ๊ฒฐ์ ํ๋ ์ธ์ฌํ ์ปจํธ๋กค์ ํ๊ธฐ ์ํด ์กด์ฌํ๋ ๊ฒ์ด ๋ฐ๋ก ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ์ด๋ค. ์ด๋ฒคํธ ๋ฃจํ๋ ๋ธ๋ผ์ฐ์ ๋ด๋ถ์ Call Stack, Callback Queue, Web APIs ๋ฑ์ ์์๋ค์ ๋ชจ๋ํฐ๋งํ๋ฉด์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ์์ ๋ค์ ๊ด๋ฆฌํ๊ณ , ์ด๋ฅผ ์์๋๋ก ์ฒ๋ฆฌํ์ฌ ํ๋ก๊ทธ๋จ์ ์คํ ํ๋ฆ์ ์ ์ดํ๋ ๋ ์์ด๋ค. ๊ฐ๋จํ ํํํ์๋ฉด ๋ธ๋ผ์ฐ์ ์ ๋์ ํ์ด๋ฐ์ ์ ์ดํ๋ ๊ด๋ฆฌ์๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
์ด๋ฒคํธ ๋ฃจํ์ ๋์ ๊ณผ์ ์ ๊ฐ๋จํ ์ดํด๋ณด์๋ฉด, ์๋ฐ์คํฌ๋ฆฝํธ์ setTimeout์ด๋ fetch ์ ๊ฐ์ ๋น๋๊ธฐ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋ธ๋ผ์ฐ์ Web APIs์๊ฒ ๋งก๊ธฐ๊ณ , ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ด ๋๋ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๋ฐฑ ํจ์ ํํ๋ก ํ(Callback Queue)์ ๋ฃ๊ณ ์ฒ๋ฆฌ ์ค๋น๊ฐ ๋๋ฉด ํธ์ถ ์คํ(Call Stack)์ ๋ฃ์ด ๋ง๋ฌด๋ฆฌ ์์
์ ์งํํ๋ค.
์ด๋ฌํ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ์ด์ฉํ ํ๋ก๊ทธ๋จ ๋ฐฉ์์ ์ด๋ฒคํธ ๊ธฐ๋ฐ(Event Driven) ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ํ๋ค. ์ด๋ฒคํธ ๊ธฐ๋ฐ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ด ์ด๋ฒคํธ์ ์ํด ๊ฒฐ์ ๋๋ ๋ฐฉ์์ด๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์์ ํด๋ฆญ์ด๋ ํค๋ณด๋ ์
๋ ฅ๊ณผ ๊ฐ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด, ๊ทธ์ ๋ง๋ ์ฝ๋ฐฑ ํจ์๊ฐ ์คํํ๋ค. ๋ํ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ addEventListener(์ด๋ฒคํธ๋ช
, ์ฝ๋ฐฑํจ์) ๊ฐ ์๊ฒ ๋ค.
์ด๋ฒคํธ ๊ธฐ๋ฐ ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก ๋น๋๊ธฐ ์์ ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ณ , ๋ฉํฐ ์ค๋ ๋ ์ธ์ด์ ๋นํด ๋จ์ํ๊ณ ์ง๊ด์ ์ธ ์ฝ๋ ์์ฑ์ ๊ฐ๋ฅํ๊ฒ ํ๋ฉฐ, ๋ธ๋ผ์ฐ์ ์ ๊ฐ์ ํ๊ฒฝ์์๋ ์์ ์ ์ธ ์คํ์ ๊ฐ๋ฅํ๊ฒ ํ์ฌ ์ฌ์ฉ์์์ ์ํธ์์ฉ์ ๋์ผ ์ ์๋ค. ๋ฐ๋ผ์ ์ด๋ฅผ ์ดํดํ๊ณ ์ ์ ํ ๋ฐฉ์์ผ๋ก ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํ๋ ๊ฒ์, ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ์์ด์ ๋งค์ฐ ์ค์ํ๋ค.
๐ก ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ ์ฑ๊ธ ์ค๋ ๋ ์ธ๊ฐ?
์๋ฐ์คํฌ๋ฆฝํธ๋ 1995๋ ์ ๋ท์ค์ผ์ดํ์์ ์น ๋ธ๋ผ์ฐ์ ์์ ๋์ ์ธ ์น ํ์ด์ง๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๊ฐ๋ฐ๋ ์คํฌ๋ฆฝํธ ์ธ์ด์ด๋ค. ๋น์์๋ ๋ฉํฐ ์ฝ์ด ํ๋ก์ธ์๊ฐ ๋ณดํธํ๋์ง ์์๊ณ , ์๋ฐ์คํฌ๋ฆฝํธ๋ ์น ๋ธ๋ผ์ฐ์ ์์ ๊ฐ๋จํ ์คํฌ๋ฆฝํธ ๋์์ ์ํํ๋ ๋ฐ ์ฃผ๋ก ์ฌ์ฉ๋์๊ธฐ ๋๋ฌธ์ ๋ณต์กํ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ํ์๋ก ํ์ง ์์, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ ๊ณ , ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ํผํ ์ ์๋ ์ฑ๊ธ ์ค๋ ๋๋ก ๊ตฌํํ์๋ค. ๊ทธ๋ฌ๋ ์ฑ๊ธ ์ค๋ ๋๋ ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ด ์คํ๋๋ฉด ๋ค๋ฅธ ์์ ๋ค์ด ๋๊ธฐํด์ผ ํ๋ฏ๋ก ์๋ต์ฑ์ด ๋จ์ด์ง๋ค. ๋ํ CPU ์ฝ์ด๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์ฑ๋ฅ์ด ์ ํ๋๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด ์ธ์ด ์์ฒด์ ์ค๊ณ๋ฅผ ๋ฐ๊พธ๋ ๊ฒ ๋ณด๋จ, ๋ธ๋ผ์ฐ์ ์ ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ด์ฉํ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ์ด ์ด๋ฒคํธ ๋ฃจํ์ธ ๊ฒ์ด๋ค. (๋ค๋ง Web worker ์ต์ ๊ธฐ์ ์ ํตํด ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ฉํฐ ์ค๋ ๋ ๊ตฌํ์ด ๊ฐ๋ฅํด์ก๋ค)
์๋ฐ์คํฌ๋ฆฝํธ ์์ง ๊ตฌ๋ ํ๊ฒฝ
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ์ํํธ์จ์ด๋ก๋ ์ฐ๋ฆฌ๊ฐ ์ ์๊ณ ์๋ ์น๋ธ๋ผ์ฐ์ ์ ๋ฐํ์์ธ Node.js ๊ฐ ์๋ค. ์ด๋ฒคํธ ๋ฃจํ ๋์ ์๋ฆฌ๋ฅผ ๋ฐฐ์ฐ๊ธฐ ์์, ์ฑ๊ธ ์ค๋ ๋์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์ด๋ ๊ณณ์ ๊ฑฐ์ณ ๋น๋๊ธฐ ์์ ์ ์ํํ๋์ง ์ฐ์ ์ด ๋์ ๋ด๋ถ ๊ตฌ์ฑ๋๋ฅผ ๋์ ์ตํ๋ณด์.
๋ณธ ํฌ์คํ ์์ ์์๋ฅผ ๋๋ ์น๋ธ๋ผ์ฐ์ ๋ Chrome ๋ธ๋ผ์ฐ์ ์ด๋ค. ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด๋ ๋ด๋ถ ๊ตฌ์ฑ์ด ์ฝ๊ฐ์ ๋ค๋ฅผ์ ์๋ค๋ ์ ์ ์ ์ํ์
๋ธ๋ผ์ฐ์ ์ ๋ด๋ถ ๊ตฌ์ฑ๋
๋ธ๋ผ์ฐ์ ๋ ์น ์ฌ์ดํธ๋ฅผ ํ๋ฉด์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ์ฌ๋ฌ๊ฐ์ง ์ญํ ์ ํ๋ ๋ถํ๋ค๋ก ์ด๋ฃจ์ด์ ธ ์๋ค. ๊ทธ์ค ์ฐ๋ฆฌ๊ฐ ์์๋ณผ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ์ฝ๋์ ๋์ ๊ณผ์ ์ด๋, ์ด์ ๊ด๋ จ๋ ๊ตฌ์ฑ ์์๋ก๋ Web APIs, Event Table, Callback Queue, Event Loop ๋ฑ์ด ์๋ค.
- Call Stack : ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์ฝ๋ ์คํ์ ์ํด ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ
- Heap : ๋์ ์ผ๋ก ์์ฑ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๊ฐ ์ ์ฅ๋๋ ๊ณต๊ฐ
- Web APIs: ๋ธ๋ผ์ฐ์ ์์ ์ ๊ณตํ๋ API ๋ชจ์์ผ๋ก, ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ์์ ๋ค์ ์ ๋ดํ์ฌ ์ฒ๋ฆฌํ๋ค. (AJAX ํธ์ถ, ํ์ด๋จธ ํจ์, DOM ์กฐ์ ๋ฑ)
- Callback Queue : ๋น๋๊ธฐ์ ์์ ์ด ์๋ฃ๋๋ฉด ์คํ๋๋ ํจ์๋ค์ด ๋๊ธฐํ๋ ๊ณต๊ฐ
- Event Loop : ๋น๋๊ธฐ ํจ์๋ค์ ์ ์ ํ ์์ ์ ์คํ์ํค๋ ๊ด๋ฆฌ์
- Event Table: ํน์ ์ด๋ฒคํธ(timeout, click, mouse ๋ฑ)๊ฐ ๋ฐ์ํ์ ๋ ์ด๋ค callback ํจ์๊ฐ ํธ์ถ๋์ผ ํ๋์ง๋ฅผ ์๊ณ ์๋ ์๋ฃ๊ตฌ์กฐ (์ ๊ทธ๋ฆผ์๋ ์์)
Web APIs์ ์ข ๋ฅ
Web APIs๋ ํ์ด๋จธ, ๋คํธ์ํฌ ์์ฒญ, ํ์ผ ์ ์ถ๋ ฅ, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ ๋ธ๋ผ์ฐ์ ์์ ์ ๊ณตํ๋ ๋ค์ํ API๋ฅผ ํฌ๊ดํ๋ ์ด์นญ์ด๋ค. Web API๋ ๋ธ๋ผ์ฐ์ (Chrome)์์ ๋ฉํฐ ์ค๋ ๋๋ก ๊ตฌํ๋์ด ์๋ค. ๊ทธ๋์ ๋ธ๋ผ์ฐ์ ๋ ๋น๋๊ธฐ ์์ ์ ๋ํด ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ด๋ค.
์๋ฅผ ๋ค์ด, setTimeout ๋น๋๊ธฐ ์์
์ Web APIs์ ํ ์ข
๋ฅ์ธ Timer API ์์ ํ์ด๋จธ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด๋จธ๋ฅผ ์ํํ๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก, XMLHttpRequest , fetch์ ๊ฐ์ ๋คํธ์ํฌ ๊ด๋ จ API๋ ๋คํธ์ํฌ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ ์์ฒญ๊ณผ ์๋ต์ ์ฒ๋ฆฌ๋๋ค.
Web APIs์ ๋ํ์ ์ธ ์ข ๋ฅ๋ก๋ ๋ค์๊ณผ ๊ฐ๋ค.
- DOM : HTML ๋ฌธ์์ ๊ตฌ์กฐ์ ๋ด์ฉ์ ํํํ๊ณ ์กฐ์ํ ์ ์๋ ๊ฐ์ฒด
- XMLHttpRequest: ์๋ฒ์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ตํํ ์ ์๋ ๊ฐ์ฒด. AJAX๊ธฐ์ ์ ํต์ฌ.
- Timer API: ์ผ์ ํ ์๊ฐ ๊ฐ๊ฒฉ์ผ๋ก ํจ์๋ฅผ ์คํํ๊ฑฐ๋ ์ง์ฐ์ํค๋ ๋ฉ์๋๋ค์ ์ ๊ณต
- Console API : ๊ฐ๋ฐ์ ๋๊ตฌ์์ ์ฝ์ ๊ธฐ๋ฅ์ ์ ๊ณต
- Canvas API:
<canvas>์์๋ฅผ ํตํด ๊ทธ๋ํฝ์ ๊ทธ๋ฆฌ๊ฑฐ๋ ์ ๋๋ฉ์ด์ ์ ๋ง๋ค ์ ์๋ ๋ฉ์๋๋ค์ ์ ๊ณต - Geolocation API: ์น ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ์์ ํ์ฌ ์์น ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ ๋ฉ์๋๋ค์ ์ ๊ณต
์ด๋ ์คํดํ์ง ๋งํ์ผํ ๊ฒ์ด ๋ชจ๋ Web API๋ค์ด ๋น๋๊ธฐ๋ก ๋์๋๋ ๊ฒ์ด ์๋๋ค. Web API์๋ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ๊ณผ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ์ด ๋ชจ๋ ์๋ค. ์๋ฅผ ๋ค์ด DOM API๋ Console API๋ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋๊ณ , XMLHttpRequest๋ Timer API๋ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
Callback Queue์ ์ข ๋ฅ
Web APIs๊ฐ ์ฌ๋ฌ API๋ค์ ๋ฌถ์ด ๋งํ๋ฏ์ด, Callback Queue๋ ์ฌ๋ฌ๊ฐ์ง ์ข ๋ฅ์ Queue๋ฅผ ๋ฌถ์ด ์ด์นญํ๋ ๊ฐ๋ ์ด๋ค. Callback Queue์๋ (macro)task queue์ microtask queue ๋ ๊ฐ์ง ์ข ๋ฅ๊ฐ ์๋ค.
- Task Queue :
setTimeout,setInterval,fetch,addEventListener์ ๊ฐ์ด ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋๋ ํจ์๋ค์ ์ฝ๋ฐฑ ํจ์๊ฐ ๋ค์ด๊ฐ๋ ํ (macrotask queue ๋ ๋ณดํต task queue ๋ผ๊ณ ๋ถ๋ฅธ๋ค) - Microtask Queue :
promise.then,process.nextTick,MutationObserver์ ๊ฐ์ด ์ฐ์ ์ ์ผ๋ก ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋๋ ํจ์๋ค์ ์ฝ๋ฐฑ ํจ์๊ฐ ๋ค์ด๊ฐ๋ ํ (์ฒ๋ฆฌ ์ฐ์ ์์๊ฐ ๋์)
Callback Queue์ ์ข ๋ฅ์ ๋ฐ๋ผ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ฝ ์คํ์ผ๋ก ์ฎ๊ธฐ๋ ์์๊ฐ ๋ฌ๋ผ์ง๋ค. ์ผ๋ฐ์ ์ผ๋ก microtask queue๊ฐ ๊ฐ์ฅ ์ฐ์ ์์๊ฐ ๋์ ๋จผ์ microtask queue๋ฅผ ์ฒ๋ฆฌํ์ฌ ๋จผ์ ๋น์ฐ๊ณ ๊ทธ๋ผ์ task queue์ ์ฝ๋ฐฑ์ ์ฒ๋ฆฌํ๋ค.
์ด๋ฒคํธ ๋ฃจํ๋ฅผ ๋ฐฐ์ฐ๊ธฐ ์ ์Promise.then๊ฒฐ๊ณผ๊ฐsetTimeout๋ณด๋ค ์ฐ์ ๋๋ค๋ ๊ฒ์ ๋ฏธ๋ฆฌ ๋ฐฐ์ ๋ค๋ฉด, ์ ํ๋ก๋ฏธ์ค๊ฐ ๋จผ์ ์ฒ๋ฆฌ๋๋์ง์ ๋ํ ์ด์ ๊ฐ ์ด๋ฒคํธ ๋ฃจํ์ ๋์ ์๋ฆฌ์ ๊ด๋ จ์ด ์๋ค๋๊ฑธ ์ ์ ์์ ๊ฒ์ด๋ค.
๋ํ ๊ฐ์ queue ์์ ์ ์ฌ๋๋ ์ฝ๋ฐฑ์ด๋ผ๋ ์ด๋ ํ ๋น๋๊ธฐ ์์ ์ด๋์ ๋ฐ๋ผ ์ฐ์ ์์๊ฐ ๋ค๋ฅธ ํ์คํฌ๋ค์ด ์์ ์ ์๋ค. ์๋ฅผ๋ค์ด Microtask Queue์ ์ ์ฌ๋๋ Promise ์ Mutation Observer ์ฝ๋ฐฑ ์ค Mutation Observer์ด ๋จผ์ ์ฒ๋ฆฌ๋๋ ์์ด๋ค.
AnimationFrame Queue
๋ธ๋ผ์ฐ์ ์ ํ๋ ์ฝ๋ฐฑ ํ ๋ฟ๋ง ์๋๋ผ ๋ธ๋ผ์ฐ์ ์ ๋๋ฉ์ด์
์์
์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋ด๋นํ๋ AnimationFrame Queue๋ ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์ ๋๋ฉ์ด์
๋์์ ์ ์ดํ๋ requestAnimationFrame ๋ฉ์๋๋ฅผ ํตํด ์ฝ๋ฐฑ์ ๋ฑ๋กํ๋ฉด, ์ด ํ์ ์ ์ฌ๋์ด ๋ธ๋ผ์ฐ์ ๊ฐ repaint ์ง์ ์ AnimationFrame Queue์ ์๋ ์์
๋ค์ ์ ๋ถ ์ฒ๋ฆฌํ๋ค. ๋ฐ๋ผ์ ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ด๋ จ ์ฝ๋๋ค์ AnimationFrame Queue์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋๋ก ๊ตฌ์ฑํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์ ๋๋ฉ์ด์
์ ํ์ด๋ฐ์ ๊ด๋ฆฌํ๊ณ , ์ ์ ํ ํ๋ ์ ์๋๋ฅผ ์ ์งํ๊ณ , ๋ค๋ฅธ ํญ์ด๋ ์ฐฝ์ ์์ ๋ ์ ๋๋ฉ์ด์
์ ์ค์งํจ์ผ๋ก์จ ๋ธ๋ผ์ฐ์ ์ ์ ๋๋ฉ์ด์
๋์์ ์ฑ๋ฅ๊ณผ ํ์ง์ ํฅ์์ํฌ ์ ์๋ค.
Node.js์ ๋ด๋ถ ๊ตฌ์ฑ๋
NodeJS ํ๊ฒฝ์์๋ ๋ธ๋ผ์ฐ์ ์ ๊ฑฐ์ ๋น์ทํ ๊ตฌ์กฐ๋ฅผ ๋ณผ ์ ์๋๋ฐ, ์ฐจ์ด์ ์ด ์๋ค๋ฉด ๋ด์ฅ๋ libuv ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ IO๋ฅผ ์ง์ํ๋ค๋ ์ ์ด๋ค. ๋ํ ๋ธ๋ผ์ฐ์ ์์๋ Web API๋ฅผ ์ฌ์ฉํ์ฌ DOM ์กฐ์, AJAX ํธ์ถ, ํ์ด๋จธ ๋ฐ ์ ๋๋ฉ์ด์
๋ฑ๊ณผ ๊ฐ์ ๋ค์ํ ์์
์ ์ฒ๋ฆฌํ์ง๋ง, Node.js์์๋ Web API๊ฐ ์๋ Node.js API๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ ์์คํ
์ก์ธ์ค, ๋คํธ์ํฌ ์ก์ธ์ค, ์ํธํ, ์์ถ ๋ฐ ํด์ ๋ฑ๊ณผ ๊ฐ์ ๋ค์ํ ์์
์ ์ฒ๋ฆฌํ๋ค. ์๋ฅผ ๋ค์ด, Node.js์์ HTTP ์์ฒญ์ ์ํํ๋ ค๋ฉด http ๋ชจ๋์ ์ฌ์ฉํ๋ค. ๋จ, Node.js์์๋ ์ผ๋ถ Web API๋ฅผ ์ฌ์ฉํ ์ ์๋๋ฐ, setTimeout, setInterval ๋ฑ์ด ๊ทธ๋ ๋ค.
์ด์ฒ๋ผ Node.js์์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋น๋๊ธฐ ์์ ์ ์ํด์ Node.js์ API๋ฅผ ํธ์ถํ๋ฉฐ, ์ด๋ ๋๊ฒจ์ง ์ฝ๋ฐฑ์ libuv ์ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ํตํด ์ค์ผ์ฅด๋๊ณ ์คํ๋๋ค. Node.js์ ๋ด๋ถ ๊ตฌ์ฑ์ผ๋ก๋ ๋ค์๊ณผ ๊ฐ๋ค.
- V8 (JavaScript ์์ง) : Node.js์์ ์ฌ์ฉํ๋ JavaScript ์์ง์ผ๋ก ์ฝ๋๋ฅผ ์ปดํ์ผํ๊ณ ์คํํ๋ค
- Bindings (Node API) : Node.js ์์คํ ๊ณผ V8 ์์ง ๊ฐ์ ์ํธ์์ฉ์ ๊ฐ๋ฅํ๊ฒ ํ๋ C++ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- Libuv ๋ผ์ด๋ธ๋ฌ๋ฆฌ : Node.js์์ ๋น๋๊ธฐ I/O ์์ ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- Event Queue : ๋น๋๊ธฐ I/O ์์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๊ณ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ฃ๊ตฌ์กฐ (์น๋ธ๋ผ์ฐ์ ์ Task Queue์ ๋น์ทํ๋ค)
- Event Loop : Event Queue์ ์ ์ฅ๋ I/O ์์ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๋ค์ ์์ ์ ์ํํ๋๋ก ํ๋ ๊ด๋ฆฌ์
- Worker Threads : CPU ์ง์ฝ์ ์ธ ์์ ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด Node.js 10 ๋ฒ์ ๋ถํฐ ์ถ๊ฐ๋ ๋ฉํฐ ์ค๋ ๋. worker threads๋ ๋ฉ์ธ ์ค๋ ๋์ ๋ ๋ฆฝ์ ์ธ V8 ์์ง ์ธ์คํด์ค๋ฅผ ๊ฐ์ง๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์ด๋ฒคํธ ๋ฃจํ ๋์ ๊ณผ์
์์ ๋ด์ฉ์ ๋ณต์ตํ์๋ฉด, ์ฑ๊ธ ์ค๋ ๋์ธ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ์์
์ ๋์ ์ฒ๋ฆฌ์ ์ง์ํ ์ ์๋ ๋น๊ฒฐ์๋ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง๊ณผ ๋ธ๋ผ์ฐ์ ์ ์น API๋ฅผ ์ฐ๊ฒฐํ์ฌ ๋น๋๊ธฐ์ ์ธ ์ผ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅ์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ค๋ง ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ ์๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์๋ ๋น๋๊ธฐ๋ก ๋์ํ๋ ๋น๋๊ธฐ ์ ์ฉ ํจ์๊ฐ ์๋๋ฐ ๋ํ์ ์ผ๋ก setTimeout ์ด๋ fetch, addEventListener ๊ฐ ์๋ค.
๋ธ๋ผ์ฐ์ ์ Web APIs๋ ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๊ฐ๊ฐ ์ ์ฉ ์์
์ ์ฒ๋ฆฌํ๋ API ์ค๋ ๋๋ค๋ก ๊ตฌ์ฑ๋ ์งํฉ์ ๋งํ๋ค. ๋ฐ๋ผ์ setTimeout ์ด ํธ์ถ๋๋ฉด Timer API ๋ผ๋ ๋ณ๋์ ์ค๋ ๋์์ ํ์ด๋จธ ๋์์ด ๋ณ๋๋ก ์คํ๋๋ ๊ฒ์ด๋ฉฐ, fetch ๊ฐ ํธ์ถ๋๋ฉด Ajax API ์ค๋ ๋์์ ๋คํธ์ํฌ ํต์ ์ด ์ด๋ฃจ์ด ์ง๋ ๊ฒ์ด๋ค.
์ด๋ฒคํธ ๋ฃจํ(Event Loop)๋ ์ด ๋น๋๊ธฐ ํจ์ ์์ ์ Web API์ ์ฎ๊ธฐ๋ ์ญํ ์ ํ๊ณ ์์ ์ด ์๋ฃ๋๋ฉด ์ฝ๋ฐฑ์ ํ(Queue)์ ์ ์ฌํ๋ค๊ฐ ๋ค์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ ์ฌํด ์ํ์ํค๋ ์ผ์ข ์ '์์ ์ ์ฎ๊ธฐ๋ ์ญํ ' ๋ง์ ํ๋ค. ์์ ์ ์ฒ๋ฆฌํ๋ ์ฃผ์ฒด๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง๊ณผ ์น API ์ด๋ค. ๊ทธ๋์ ์ด๋ฒคํธ ๋ฃจํ๋ Call Stack์ ํ์ฌ ์คํ ์ค์ธ ์์ ์ด ์๋์ง ๊ทธ๋ฆฌ๊ณ Task Queue์ ๋๊ธฐ ์ค์ธ ์์ ์ด ์๋์ง ๋ฐ๋ณต์ ์ผ๋ก ํ์ธํ๋ ์ผ์ข ์ ๋ฌดํ ๋ฃจํ๋ง์ ๋๊ณ , ๋๊ธฐ ์์ ์ด ์๋ค๋ฉด ์์ ์ ์ฎ๊ฒจ์ฃผ๋ ํํ๋ก ๋์ํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค. (๊ทธ๋์ ์ด๋ฒคํธ '๋ฃจํ' ์ด๋ค)
// ์ด๋ฒคํธ ๋ฃจํ์ ๋์์ ๋ํ๋ด๋ ๊ฐ์์ ์ฝ๋
while(queue.waitForMessage()){ // ํ์ ๋ฉ์์ง๊ฐ ์์ ๋๊น์ง ๋๊ธฐ
queue.processNextMessage(); // ๊ฐ์ฅ ์ค๋๋ ๋ฉ์์ง๋ฅผ ํ์์ ๊บผ๋ด์ ํธ์ถ ์คํ์ผ๋ก ์ฎ๊น
}
์ง๊ธ๋ถํฐ ์์๋ณผ ์ด๋ฒคํธ ๋ฃจํ ๋์ ๊ณผ์ ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ๋ธ๋ผ์ฐ์ ๋ด๋ถ์์ ์์ ์ด๋์ด ์ด๋ ํ ํ์์ผ๋ก ์ด๋ ํ ์๋ฆฌ๋ก ์งํ์ด ๋๋์ง ์์๋ณด๋ ๊ฒ์ด๋ค. ๋ง์นจ ์๋ฐ์คํฌ๋ฆฝํธ ์ด๋ฒคํธ ๋ฃจํ ๊ณผ์ ์ Lydia Hellie ๋ถ์ด ์์ฃผ ๊ณ ํ๋ฆฌํฐ๋ก gif ์ ๋๋ฉ์ด์ ์ผ๋ก ํํํ ์ด๋ฏธ์ง๊ฐ ์์ด์ ์ด๋ฅผ ์ฐธ๊ณ ํ์ฌ ์๊ฐํด๋ณธ๋ค.
setTimeOut ๋ด๋ถ ๋์ ๊ณผ์
์ฐ์ ๊ฐ์ฅ ํํ ํ์ด๋จธ ๋น๋๊ธฐ ํจ์์ ์ด๋ฒคํธ ๋ฃจํ ๊ณผ์ ์ ์์๋ณด๋๋ก ํ์.
function bar() {
setTimeout(() => {
console.log("Second")
}, 500);
}
function foo() {
console.log("First");
}
function baz() {
console.log("Third");
}
bar();
foo();
baz();
์์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์คํ ๊ณผ์ ์ ๋ค์์ ์์๋ก ์งํ๋๋ค.
bar()ํจ์๊ฐ ํธ์ถ๋๊ณ ๊ทธ์์setTimeout()ํจ์๊ฐ ํธ์ถ๋์ด ์คํ์ ์์ธ๋ค.setTimeout()ํจ์์ ๋งค๊ฐ๋ณ์์ ํ ๋น๋ ์ฝ๋ฐฑ ํจ์๋ฅผ Timer Web API์ ์ ๋ฌํ๋ค. ๊ทธ๋ฆฌ๊ณ Timer Web API ์์๋ ๋ฐฑ๊ทธ๋ผ์ด๋๋ก 500 ๋ฐ๋ฆฌ์ด๋ฅผ ์ ํ๋ค.- ๋ค์
foo()ํจ์๊ฐ ํธ์ถ๋๊ณ ์ฝ์์ฐฝ(output)์ "First" ๊ฐ ์ถ๋ ฅ๋๋ค. - ์ด๋ 500 ๋ฐ๋ฆฌ์ด ๋๊ธฐ ์๊ฐ์ด ๋ง๋ฃ๋๋ฉด์, ์ด๋ฒคํธ ๋ฃจํ๋Timer Web API์์ ๊ฐ์ง๊ณ ์๋ ์ฝ๋ฐฑ ํจ์๋ฅผ Task Queue ๋ก ์ฎ๊ธด๋ค.
- ๊ทธ๋ค์
baz()ํจ์๊ฐ ํธ์ถ๋๊ณ ์ฝ์์ฐฝ์ "Third" ๊ฐ ์ถ๋ ฅ๋๋ค. - ์คํ์ ์๋ ๋ชจ๋ ๋ฉ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์คํ ์๋ฃ ๋์ด Call Stack์ด ๋น์์ง๊ฒ ๋๋ค.
- ์ด๋ฒคํธ ๋ฃจํ๋ Call Stack ์ด ๋น์ด์๋ ๊ฒฝ์ฐ๋ฅผ ํ์งํ์ฌ, Task Queue ์ ์๋ ์ฝ๋ฐฑ ํจ์๋ฅผ Call Stack ์ผ๋ก ์ฎ๊ธด๋ค.
- Call Stack ์์ ์ฝ๋ฐฑ ํจ์ ์ฝ๋๋ฅผ ์คํํ๊ฒ ๋๊ณ ์ฝ์์ฐฝ์๋ "Second" ๊ฐ ์ถ๋ ฅ๋๋ค.
์ด ๋์ ์๋ฆฌ์ ํต์ฌ์ ํน์ ํ ์์
์ ๋ํด ๋น๋๊ธฐ๋ก ๋ฉํฐ ์์
์ ํ ์ ์๋ค๋ ๊ฒ์ด๋ค. ๋น๋๊ธฐ ๋์ ์์๊ฐ ๊ณ ์ ํ์ด๋จธ๋ฅผ ์
ํ๋ setTimeout ์ด๋ผ ์ ์๋ฟ์ง ์์ ์ ์๋ค. ํ์ง๋ง ํ์ผ ์
์ถ๋ ฅ์ด๋ ํค๋ณด๋ ํ์ดํ ํ๋ ์ด๋ฒคํธ ๋์์ผ ๊ฒฝ์ฐ๋ผ๋ฉด ์ด๋ป๊น? ๋น๋๊ธฐ๊ฐ ์๋ค๋ฉด ํ์ผ์ ๋ค์ด ๋ฐ๊ฑฐ๋ ํค๋ณด๋๋ฅผ ํ์ดํ ํ๋ ๋์์๋ ๋์ ์น์ฌ์ดํธ๋ ๋ฉ์ถ๊ฒ ๋์ด ์๋ฌด๊ฒ๋ ๋ชปํ๊ฒ ๋ ๊ฒ์ด๋ค. ๋ฐ๋ก ์ด๋ฒคํธ ๋ฃจํ๋ ์ด๋ฌํ ์์
๋ค์ ๋ณ๋๋ก ๋ธ๋ผ์ฐ์ ์ ๋ฉํฐ ์ค๋ ๋์๊ฒ ์ธ๊ฐํ์ฌ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํด์ฃผ๋ ํธ๋ค๋ฌ ์ญํ ์ ํ๋ ๊ฒ์ด๋ค.
์น๋ธ๋ผ์ฐ์ ์ Node.js์ Web API ์ฐจ์ด
์น๋ธ๋ผ์ฐ์ ์ Web APIs ์ Node.js ์ Node.js APIs ๋ค์ ๊ตฌ์ฑ์ ๋น์ทํ์ง๋ง ๋์ ์ธก๋ฉด์์ ์ฝ๊ฐ ์ฐจ์ด๊ฐ ์๋ค. ์น๋ธ๋ผ์ฐ์ ์ Web APIs๋ ๋น๋๊ธฐ ์์ ์ด ๋๋๋ฉด ์ค์ค๋ก callback queue์ ์ ์ฌํ์ง๋ง, Node.js API๋ค์ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ง์ ์ฎ๊ฒจ์ค๋ค. ์๋ฅผ๋ค์ด Timer Web API์์ ํ์ด๋จธ๊ฐ ๋ชจ๋ ์ง๋๊ฐ๋ฉด, ์๋ฐ์คํฌ๋ฆฝํธ ํ๊ฒฝ์ด ์น๋ธ๋ผ์ฐ์ ๋ Node.js ๋์ ๋ฐ๋ผ ์ฐจ์ด๊ฐ ๊ฐ๋ฆฐ๋ค.
- Node.js : Timer API๊ฐ ํ์ด๋จธ ์๋ฃ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ณ , ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ด๋ฅผ ๊ฐ์งํ์ฌ Task Queue์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ถ๊ฐํ๋ค.
- ์น๋ธ๋ผ์ฐ์ : Timer API๊ฐ ์ค์ค๋ก Task Queue์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ถ๊ฐํ๋ค.
Promise ๋ด๋ถ ๋์ ๊ณผ์
Task Queue ์ Microtask Queue
Callback Queue๋ Web API๊ฐ ์ํํ ๋น๋๊ธฐ ํจ์๋ฅผ ๋๊ฒจ๋ฐ์ Event Loop๊ฐ ํด๋น ํจ์๋ฅผ Call Stack์ ๋๊ฒจ์ค ๋๊น์ง ๋น๋๊ธฐ ํจ์๋ค์ ์์๋๋ ๊ณณ์ด๋ค. ์์์ Callback Queue์ ์ข ๋ฅ์๋ (Macro)Task Queue, MicroTask Queue 2๊ฐ์ง๊ฐ ์๋ค๊ณ ํ์๋๋ฐ, ๊ทธ์ค ์๋ฐ์คํฌ๋ฆฝํธ Promise ๊ฐ์ฒด์ ์ฝ๋ฐฑ์ด ์์ด๋ ๊ณณ์ด ๋ฐ๋ก MicroTask Queue์ด๋ค. ๊ทธ๋ฆฌ๊ณ MicroTask Queue๋ ๊ทธ ์ด๋ค ๊ณณ๋ณด๋ค ๊ฐ์ฅ ๋จผ์ ์ฐ์ ์ผ๋ก ์ฝ๋ฐฑ์ด ์ฒ๋ฆฌ๋๊ฒ ๋๋ค. (์ฌ์ง์ด ๋ธ๋ผ์ฐ์ ํ๋ฉด ๋ ๋๋งํ๊ธฐ ์ ๋ณด๋ค ๋ง์ด๋ค)
MicroTask Queue ์ฒ๋ฆฌ ๊ณผ์
์ค์ ์์ ์ฝ๋์์ setTimeout ๊ฐ Promise ๊ฐ์ฒด์ ์ฝ๋ฐฑ์ด ๋์์ ์ฃผ์ด์ก์๋ ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋๋์ง ํ์ธํด๋ณด์. ์ฝ๋ ๋ด์ฉ์ ์ดํด๋ณด๋ฉด ๋จผ์ setTimeout ์ ํตํด์ 0์ด๋์ ๋๊ธฐ ํ์๋ค๊ฐ "Timeout!" ์ ์ถ๋ ฅํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค. ๊ทธ๋ค์ Promise ๊ฐ์ฒด์ ์ํด "Promise!" ๋ผ๋ ํ ์คํธ๋ฅผ ์ถ๋ ฅํ๋ then ํธ๋ค๋ฌ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํ๋ค. ์ด ์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด ์๋์ ๊ฐ์ด ๋์ ์ ๋๋ฉ์ด์ ์ด ๋ฐ์ํ๋ค.
console.log('Start!');
setTimeout(() => {
console.log('Timeout!');
}, 0);
Promise.resolve('Promise!').then(res => console.log(res));
console.log('End!');
1. Call Stack์ console.log('Start!') ์ฝ๋ ๋ถ๋ถ์ด ์์ธ ๋ค ์คํ ๋์ด ์ฝ์์ฐฝ์ "Start!" ๊ฐ ์ถ๋ ฅ
2. setTimeout ์ฝ๋๊ฐ ์ฝ ์คํ์ ์ ์ฌ๋๊ณ ์คํ๋๋ฉด, ๊ทธ ์์ ์ฝ๋ฐฑ ํจ์๊ฐ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด Web API๋ก ์ฎ๊ฒจ์ง๊ณ ํ์ด๋จธ๊ฐ ์๋ํ๊ฒ ๋๋ค. (0์ด๋ผ์ ์ฌ์ค์ ๋ฐ๋ก ํ์ด๋จธ๋ ์ข
๋ฃ๋๋ค)
3. ํ์ด๋จธ๊ฐ ์ข
๋ฃ๋จ์ ๋ฐ๋ผ setTimeout ์ ์ฝ๋ฐฑ ํจ์๋ MacroTask Queue์ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด ์ ์ฌ๋๊ฒ ๋๋ค.
4. Promise ์ฝ๋๊ฐ ์ฝ์คํ์ ์ ์ฌ ๋์ด ์คํ๋๊ณ then ํธ๋ค๋ฌ์ ์ฝ๋ฐฑ ํจ์๊ฐ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด MicroTask Queue์ ์ ์ฌ๋๊ฒ ๋๋ค.
5. console.log('End!') ์ฝ๋๊ฐ ์คํ๋๊ณ "End!" ํ
์คํธ๊ฐ ์ฝ์์ฐฝ์ ์ถ๋ ฅ๋๋ค.
6. ๋ชจ๋ ๋ฉ์ธ ์ค๋ ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์คํ์ด๋์ด ๋์ด์ Call Stack์ ์คํํ ์คํ์ด ์์ด ๋น์์ง๊ฒ ๋๋ค.
7. ๊ทธ๋ฌ๋ฉด ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ด๋ฅผ ๊ฐ์งํ์ฌ, Callback Queue์ ๋จ์์๋ ์ฝ๋ฐฑ ํจ์๋ค์ ๋นผ์ Call Stack์ ์ ์ฌํ๊ฒ ๋๋ค.
8. ์ด๋ 2์ข ๋ฅ์ Queue ์ค MicroTask Queue์ ๋จ์์๋ ์ฝ๋ฐฑ์ด ์ฐ์ ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ค. (๋ง์ผ ์ฝ๊ฐ์ด ์ฌ๋ฌ๊ฐ๊ฐ ์๋ค๋ฉด ์ ๋ถ ์ฒ๋ฆฌ๋๋ค)
9. MicroTask Queue๊ฐ ๋น์ด์ง๋ฉด, ์ด์ ์ด๋ฒคํธ ๋ฃจํ๋ MacroTask Queue์ ์๋ ์ฝ๋ฐฑ ํจ์๋ฅผ Call Stack์ ์ ์ฌํด ์คํ๋๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์ต์ข ์ฝ๋์ ์คํ ์์๋ ์๋์ ๊ฐ์ด ๋๋ค.
Async/Await ๋ด๋ถ ๋์ ๊ณผ์
์๋ฐ์คํฌ๋ฆฝํธ์ Async/Await ๋ ๋น๋๊ธฐ ๋
ผ๋ธ๋กํน ๋์์ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ES7 ๋ถํฐ ์๋กญ๊ฒ ๋์
๋ ๊ฒ์ผ๋ก ๋ณต์กํ ์ฝ๋ฐฑ์ด๋ then ํธ๋ค๋ฌ์ ์ง์ฅ(hell) ์ฝ๋๋ฅผ ๊ทน๋ณตํ๋ ํต์ฌ์ด๋ค. Async/Await ์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ ๋ฌธ๋ฒ์ ๋ํด์๋ ๋
์๋ถ๋ค๋ ์ตํ ์๊ณ ์์ ๊ฒ์ด๋ค. ํ์ง๋ง ๋ง์ ์ฌ๋๋ค์ด Async/Await ์ ๋จ์ํ ๋น๋๊ธฐ๋ฅผ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํด์ค๋ค๋ ํจ๊ณผ๋ง ์๊ณ ์์ด์์ธ์ง, ๋น๋๊ธฐ ์ฝ๋์ ๋๊ธฐ ์ฝ๋๊ฐ ๊ฐ์ด ์ฐ์ฌ์ ธ ์์ ๊ฒฝ์ฐ ์ด๋ค์ ํ์คํ ์ฒ๋ฆฌ ๊ณผ์ ์ ์ ํํ๊ฒ ์์ง ๋ชปํ๋ค.
์๋ฅผ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด async ํจ์๋ฅผ ๋์ผ ์ฝ๋ ๋ ๋ฒจ์์ ์คํํ๋ค๊ณ ํด๋ณด์.
const one = () => Promise.resolve('One!');
async function myFunc(){
console.log('In function!');
const res = await One();
console.log(res);
}
console.log('Before Function!');
myFunc();
console.log('After Function!');
1. ์ฝ์์ 'Before Function!' ์ด ์ถ๋ ฅ๋๋ค.
2. async ํจ์์ธ myFunc() ์ด ํธ์ถ๋๋ค.
3. async ํจ์ ์์ ์๋ ์ฝ์ ํจ์๊ฐ ์คํ๋์ด ์ฝ์์ 'In Function!' ์ด ์ถ๋ ฅ๋๋ค.
๊ฐ๋ async ํจ์๋ฅผ ๋ฉ์ธ ์ฝ๋๊ฐ ๋ชจ๋ ์คํ๋์ด์ผ ๋์ค์ ์คํ๋๋ ๋น๋๊ธฐ ํจ์๋ก ์๊ณ ์๋ ์ฌ๋๋ค์ด ๋ง์๋ฐ, async ํจ์๋ ๋ธ๋ญ ๋ด๋ถ์์ await ํค์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํจ์ ํค์๋ ์ผ ๋ฟ ๊ทธ๋ฅ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ์กฐ๊ธ ํน๋ฒฝํ ์ผ๋ฐ์ ์ธ ํจ์์ด๋ค. ๋ฐ๋ผ์ async ํจ์๋ผ๋ ์ผ๋ฐ ํจ์์ฒ๋ผ ํธ์ถ ์คํ์ด ์์ด๊ณ , async ํจ์ ๋ด์ ๋น๋๊ธฐ๊ฐ ์๋ ๋๊ธฐ ์ฝ๋๋ ์ผ๋ฐ ์ฝ๋์ ๊ฐ์ด ์คํ๋๋ค.
4. Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ one() ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๋ค.
5. ์ด๋ one() ๋น๋๊ธฐ ํจ์ ์ผ์ชฝ์ await ํค์๋๋ก ์ธํด, myFunc ํจ์์ ๋ด๋ถ ์คํ์ ์ ์ ์ค๋จ๋๊ณ Call stack ์์ ๋น ์ ธ๋์ ๋๋จธ์ง ๋ถ๋ถ์ Microtask Queue ์ ์ ์ฌ๋๋ค. ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด await ํค์๋๋ฅผ ์ธ์ํ๋ฉด async ํจ์์ ์คํ์ ์ง์ฐ๋๋ ๊ฒ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
6. ๋ง์ง๋ง์ผ๋ก ์ฝ์์ 'After Function!' ์ด ์ถ๋ ฅ๋๋ค.
7. ๋ชจ๋ ๋ฉ์ธ ์ค๋ ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์คํ์ด๋์ด ๋์ด์ Call Stack์ ์คํํ ์คํ์ด ์์ด ๋น์์ง๊ฒ ๋๋ค.
8. ๊ทธ๋ฌ๋ฉด ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ด๋ฅผ ๊ฐ์งํ์ฌ, Microtask Queue์ ๋จ์์๋ async ํจ์๋ฅผ ๋นผ์ Call Stack์ ์ ์ฌํ๊ฒ ๋๋ค.
8. Promise ๊ฐ์ฒด์ ๊ฒฐ๊ณผ๋ฌผ์ธ 'One!' ๋ฌธ์์ด์ ๋ณ์ res ์ ๋ฐ๊ณ ์ด๋ฅผ ์ฝ์์ ์ถ๋ ฅํ๋ค.
Async/Await ์คํด์ ์ง์ง ๋์
๊ทธ๋ผ ์ด๋ฒ์๋ myFunc() ํจ์๋ฅผ ํธ์ถํ๋ ๋ฉ์ธ ์คํ์์ await ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ์ฐธ๊ณ ๋ก ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ์ต์์ await ์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ณ๋๋ก ์ฆ์ ์คํ IIFE๋ฅผ ๋ฌถ์ง ์์๋ ๋์์ด ๊ฐ๋ฅํ๋ค.
const one = () => Promise.resolve('One!');
async function myFunc(){
console.log('In function!');
const res = await one();
console.log(res);
}
console.log('Before Function!');
await myFunc();
console.log('After Function!');
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, ์์ Async/Await ์ฒ๋ฆฌ ๊ณผ์ 1 ๊ณผ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋๊ฑธ ๋ณผ ์ ์๋ค. ์ผ๋จ ๊ธฐ๋ณธ์ ์ธ Async/Await ๋ฌธ๋ฒ ๊ฐ๋ ์ ์๊ณ ์๋ค๋ฉด ์ด ๋ถ๋ถ์ ๊ทธ๋ ๊ฒ ์ด๋ ต์ง ์์ ๊ฒ์ด๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ง๊ธ ์ด๋ฒคํธ ๋ฃจํ ๋์์ ๋ํด ๋ฐฐ์ฐ๊ณ ์๋ค. ๊ทธ๋ผ ์ ์ต์์ await ์ฝ๋ ๋์์ ์ด๋ฒคํธ ๋ฃจํ๋ก ๋ด๋ถ์ ์ผ๋ก ๋ฐ์ ธ๋ณด์.
์๋ง ๋ง์ ์๋ด๊ธฐ๋ค์ด ์ฌ๊ธฐ์ ๋งํ ๊ฒ์ด๋ค. ์ฐ๋ฆฌ๋ await ํค์๋๋ฅผ ์ฌ์ฉํ๋ Promise ๋ฐํ ๋น๋๊ธฐ one() ํจ์์ ๊ฒฐ๊ณผ ์ฝ๋ฐฑ์ด Microtask Queue์ ์ ์ฌ๋๋ค๋ ๊ฒ์ ์๊ณ ์๋ค. ๊ทธ๋ฐ๋ฐ Microtask Queue์ ์ฝ๋ฐฑ๋ค์ ์ฐ์ ๋ฉ์ธ Call Stack์ด ๋น์์ ธ ์์ด์ผ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ฎ๊ฒจ ์ฒ๋ฆฌํ๋ค. ํ์ง๋ง ์์ง ๋ฉ์ธ Call Stack์๋ console.log(‘After Function!’) ์ด ๋จ์ ์๋ค. ๊ทธ๋ฐ๋ฐ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด console.log(‘After Function!’) ์ด ์คํ๋๊ธฐ ์ ์ await myFunc() ๋จผ์ ์ฒ๋ฆฌ๋๊ณ ์ฝ์์ ์ถ๋ ฅํจ์ ๋ณผ ์ ์๋ค.
์ด๊ฒ ์ด๋ป๊ฒ ๋ ์ผ ์ผ๊น? ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๋ฐฐ์ด ์ด๋ฒคํธ ๋ฃจํ ๋์์ด ์๋ชป๋ ๊ฒ์ผ๊น?
์ฌ์ค Async/Await์ ์ง์ง ๋์์ ๋ค์๊ณผ ๊ฐ๋ค. ์๋ฅผ ๋ค์ด, ์๋์ ๊ฐ์ ์ฝ๋๊ฐ ์๋ค๊ณ ํ์.
let x = await bar(); // bar() ํจ์ ์ ์๋ ์๋ต
console.log(x);
console.log('Done');
์์ ์ฝ๋๋ ์ฌ์ค ๋ค์๊ณผ ๊ฐ์ ์ฝ๋์ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ค.
bar().then(x => {
console.log(x);
console.log('Done');
});
์ฆ, await ํค์๋ ๋ค์์ ๋์ค๋ ๋์ผ ๋ผ์ธ์ ์ฝ๋๋ค์ ๋ชจ๋ await bar() ์ then ํธ๋ค๋ฌ์ ์ฝ๋ฐฑ ํจ์๋ก ๋ค์ด๊ฐ๋ค๋ ๋ป์ด๋ค.
์ค์ ๋ก async/await ํค์๋๋ promise.then() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ๋ฌธ๋ฒ์ ์ธ ํธ์ ๊ธฐ๋ฅ(syntactic sugar)์ผ ๋ฟ์ด๋ค. ์ฆ, async/await ํค์๋๋ promise.then() ๋ฉ์๋๋ฅผ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋ผ, promise.then() ๋ฉ์๋๋ฅผ ๊ฐ๊ฒฐํ๊ณ ๋ช
ํํ๊ฒ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์ต์ข
์ ๋ฆฌํ์๋ฉด myFunc() ์ฝ๋๋ ํ๋ก๋ฏธ์ค ํธ๋ค๋ฌ๋ก ํ๋ฉด ์๋์ ๊ฐ์ด ๊ตฌ์ฑ๋๊ฒ ๋๊ณ , ๊ฐ then ํธ๋ค๋ฌ๋ค์ด MicroTask Queue์ ์ฐจ๊ณก ์ฐจ๊ณก ์์์ผ๋ก์จ ์์๋๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ด๋ค.
const one = () => Promise.resolve('One!');
async function myFunc(){
console.log('In function!');
const res = await one();
console.log(res);
}
console.log('Before Function!');
await myFunc();
console.log('After Function!');
/* ---------------- ↓↓↓ ๋ณํ ↓↓↓ ---------------- */
const one = () => Promise.resolve('One!');
function myFunc(){
console.log('In function!');
return one().then(res => {
console.log(res);
});
}
console.log('Before Function!');
myFunc().then(() => {
console.log('After Function!');
});
์ฆ, await myFunc() ๋ค์์ ๋์ค๋ ์ฝ๋๋ค์ด myFunc()์ then ํธ๋ค๋ฌ์ ์ฝ๋ฐฑ์ผ๋ก์ Microtask Queue์ ์ ์ฌ๋๊ณ ์ด๋ฒคํธ ๋ฃจํ์ ๋ค์ Call stack์ ์ฎ๊ฒจ์ ธ์ ์คํ๋๋ ๊ฒ์ด๋ค.
MicroTask Queue์ ๋ฌดํ ๋ฃจํ
Task Queue์ MicroTask Queue์ ์ฐจ์ด์ ์ ๋จ์ํ ์ฐ์ ์์ ์ฐจ์ด ์ ๋ ๋ฐ์ ์์ง๋ง, ์ข๋ ํ์ฅํด์ ๋ธ๋ผ์ฐ์ ๋์ ๊ด์ ์์ ๋ณด๋ฉด ์ด๋ ๊ต์ฅํ ์ค์ํ ์์์ด๋ค. MicroTask Queue์ ์ฝ๋ฐฑ์ ๊ฐ์ฅ ๋์ ์ฐ์ ์์๋ก ์ฒ๋ฆฌ๋์ง๋ง ์ด๋ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ๋ ๋๋งํ๋ ๊ณผ์ ๋ณด๋ค ๋ ๋จผ์ ์ฒ๋ฆฌ๋๊ฒ ๋๋๋ฐ, ๋ง์ผ MicroTask Queue์ ์๋ชป๋ ๋ฌดํ ๋ฃจํ ๋์์ ๋ฒ๊ทธ์ ์ฝ๋๊ฐ ๋ค์ด๊ฐ๊ฒ ๋๋ฉด ์นํ์ด์ง๊ฐ ๋จนํต์ด ๋์ด๋ฒ๋ฆฌ๋ ํ์์ด ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ ์ฝ๋๋ฅผ ๋ด๋ณด์. ๋ฒํผ์ด ํ๋ ์๊ณ ์ฌ๊ธฐ์ ์ด๋ฒคํธ ์ฝ๋ฐฑ์ด ๋ฑ๋ก ๋์ด ์๋ค. ์ด ์ด๋ฒคํธ ์ฝ๋ฐฑ์ Task Queue์ ์ ์ฌ๋์ด ์คํ๋๊ฒ ๋๋ค.
<button id="btn">Click me</button>
<script>
// ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฝ์์ Clicked๋ฅผ ์ถ๋ ฅํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
document.getElementById("btn").addEventListener("click", () => {
document.body.insertAdjacentHTML('beforeend', "<p>Clicked</p>");
});
</script>
See the Pen MicroTask Queue์ ๋ฌดํ ๋ฃจํ 1 by barzz12 (@inpaSkyrim) on CodePen.
์ด ์ํ์์ ํ๋ฒ setTimeout ๋ฌดํ ๋ฃจํ๋ฅผ ๊ตฌํํด๋ณด์. ์๋ '๋ฌดํ๋ฃจํ ์์' ๋ฒํผ์ ๋๋ฅด๋ฉด ํ์ด๋จธ๊ฐ ๊ณ์ ๋์ฌ "Loop" ์ฝ์์ ์ถ๋ ฅํ ๊ฒ์ด๋ค. ๊ทธ ์ํ์์ ๋ฒํผ์ Click me ํด๋ณด์. ์๋ฌด ์ด์ ์์ด ํ๋ฉด์ 'Clicked'๊ฐ ํ์๋ ๊ฒ์ด๋ค.
setTimeout ์ ๋ฃจํ ์ฝ๋ฐฑ์ด Task Queue์ ์ค์๊ฐ์ผ๋ก ์ ์ฌ๋๋ฉด์ ์ฒ๋ฆฌ๋๋ ๋์ค, ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๋ฉด ์ด๋ฒคํธ ์ฝ๋ฐฑ ์ญ์ Task Queue์ ์ ์ฌ๋์ด ์คํ์ด ๋๊ธฐ ๋๋ฌธ์, ๋น๋ก ๋ฌดํ ๋ฃจํ ์ฝ๋๋ผ๋ ๋ธ๋ผ์ฐ์ ๋์ ์์ฒด๋ ๋ฌธ์ ์๋ ๊ฒ์ด๋ค.
<button id="btn">Click me</button>
<button id="btn2">๋ฌดํ๋ฃจํ ์์</button>
<div id="loopArea" style="border: 1px solid black; max-height: 150px; overflow-y: auto;"></div>
<script>
// ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฝ์์ Clicked๋ฅผ ์ถ๋ ฅํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
document.getElementById("btn").addEventListener("click", () => {
document.body.insertAdjacentHTML('beforeend', "<p>Clicked</p>");
});
document.getElementById("btn2").addEventListener("click", () => {
// setTimeout ํจ์๋ Task Queue์ ์ฝ๋ฐฑ์ ์ถ๊ฐ
function loop() {
setTimeout(() => {
document.getElementById("loopArea").append("Loop\n");
loop(); // loop ํจ์๊ฐ setTimeout ๊ฐ์ฒด์ ์ฝ๋ฐฑ์ผ๋ก ์์ ์ ๊ณ์ํด์ ์ถ๊ฐ
}, 0);
}
// loop ํจ์๋ฅผ ํธ์ถ
loop();
});
</script>
See the Pen MicroTask Queue์ ๋ฌดํ ๋ฃจํ 2 by barzz12 (@inpaSkyrim) on CodePen.
์ด๋ฒ์๋ Promise ๊ฐ์ฒด๋ฅผ ์ด์ฉํด ์ฌ๊ท ํจ์ ํธ์ถ๋ก ๋ฌดํ ๋ฃจํ๋ฅผ ๊ตฌํํด ๋ณด์. ๋กํ ๋์ ์ฝ๋ ์์ฒด๋ ์์ setTimeout๊ณผ ๋ณ๋ค๋ฅธ ์ฐจ์ด๊ฐ ์๋ค. ๋ค๋ง ์ด ๋ฃจํ ์ฝ๋ฐฑ์ด Task Queue ๊ฐ ์๋ MicroTask Queue์ ๋ค์ด๊ฐ๋ค๋ ์ฐจ์ด์ ์ด ์๋๋ฐ, MicroTask Queue ๊ฐ ๋ฌดํ ๋ฃจํ์ ๋น ์ง๊ฒ ๋๋ฉด ์ด๋ป๊ฒ ๋๋์ง ๋ณด์. (์๋น ๋ธ๋ผ์ฐ์ ๋ฅผ ํ๋ ์ค๋นํด์ ํ
์คํธํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค)
<button id="btn">Click me</button>
<button id="btn2">๋ฌดํ๋ฃจํ ์์</button>
<div id="loopArea" style="border: 1px solid black; max-height: 150px; overflow-y: auto;"></div>
<script>
// ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฝ์์ Clicked๋ฅผ ์ถ๋ ฅํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
document.getElementById("btn").addEventListener("click", () => {
document.body.insertAdjacentHTML('beforeend', "<p>Clicked</p>");
});
document.getElementById("btn2").addEventListener("click", () => {
// Promise ๊ฐ์ฒด๋ MicroTask Queue์ ์ฝ๋ฐฑ์ ์ถ๊ฐ
function loop() {
Promise.resolve().then(() => {
document.getElementById("loopArea").append("Loop\n");
loop(); // loop ํจ์๊ฐ Promise ๊ฐ์ฒด์ ์ฝ๋ฐฑ์ผ๋ก ์์ ์ ๊ณ์ํด์ ์ถ๊ฐ
});
}
// loop ํจ์๋ฅผ ํธ์ถ
loop();
});
</script>
See the Pen MicroTask Queue์ ๋ฌดํ ๋ฃจํ 3 by barzz12 (@inpaSkyrim) on CodePen.
์น์ฌ์ดํธ๊ฐ ๋จนํต์ด ๋์ด ๋ฒ๋ฆด ๊ฒ์ด๋ค. ๋๊ฐ์ ๋ฌดํ ๋ฃจํ ๋์์ธ๋ฐ ํ๋๋ ์น์ฌ์ดํธ ๋์์ ๋ฌธ์ ๊ฐ ์์๊ณ , ํ๋๋ ์น์ฌ์ดํธ ์์ฒด๊ฐ ๋ธ๋ฝ์ด ๋์ด๋ฒ๋ ค ์ด๋ ํ ๋์์ ํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค. ์๋ํ๋ฉด MicroTask Queue๊ฐ ๋น์ด์์ง ์์ผ๋ฏ๋ก ๋ค๋ฅธ ๋งคํฌ๋กํ์คํฌ๋ ์ด๋ฒคํธ ์ฝ๋ฐฑ์ด ์คํ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฌดํ ๋ฃจํ ์ฝ๋ ๋๋ฌธ์ ๋์์์ด MicroTask Queue์ ์ฝ๋ฐฑ์ด ์ ์ฌ๋๊ฒ ๋๊ณ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ด๋ค์ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๋ ๋๋ง์ ํ๊ธฐ์ ์ ์ฐ์ ์ผ๋ก ๋์ ์์ด ์ฒ๋ฆฌ ๋ ์ฒ๋ฆฌํ๊ณ ์๊ธฐ ๋๋ฌธ์, ๊ฒฐ๊ตญ ์ฌ์ฉ์ ์ด๋ฒคํธ์ ๋ฐ์ํ์ง ๋ชปํ๊ณ , ํ์ด์ง๊ฐ ๋ฉ์ถ๊ฑฐ๋ ์๋ตํ์ง ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
์ด ์์ ์ฝ๋์ ์ฌ๋ก๋ ์กฐ๊ธ ๊ทน๋จ์ ์ธ ์ต์ง ์ฝ๋๋ผ ์ ์๋ฟ์ง ์์ ์ ์๋ค. ํ์ง๋ง ์ด ํํธ์ ํต์ฌ์ ๋ง์ผ MicroTask Queue๋ฅผ ์ฌ์ฉํ๋ Promise ์ฝ๋๋ Mutation Observer ์ ์ฝ๋ฐฑ์์ ๋ฌดํ ๋ฃจํ ๊น์ง๋ ์๋๋๋ผ๋ ์ง๋์น๊ฒ MicroTask Queue์ ์ฝ๋ฐฑ์ ์ง๋์น๊ฒ ์ ์ฌํ๋ ์์ ์ด ์๋ค๋ฉด ์ด๋ฅผ ์กฐ์ฌํ ๋ค๋ฃจ์ด์ผ ํ๋ค๋ ์ ์ด๋ค.
Animation Frames
Animation Frames๋ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ๋ค์ ๊ทธ๋ฆด ๋ ์คํ๋๋ ํจ์๋ค์ ๋ด์๋๋ ๊ณณ์ด๋ค. ์๋ฅผ ๋ค์ด, ์น ํ์ด์ง์์ ์์ง์ด๋ ๋๊ทธ๋ผ๋ฏธ๋ฅผ ๊ทธ๋ฆฌ๊ณ ์ถ๋ค๋ฉด, requestAnimationFrame์ด๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํด์ ๋๊ทธ๋ผ๋ฏธ์ ์์น๋ฅผ ๋ฐ๊ฟ์ฃผ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฃ์ด์ค Animation Frames์ ์ ์ฌ๋์ด ์คํ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ๊ฐฑ์ ํ ๋๋ง๋ค ๋๊ทธ๋ผ๋ฏธ์ ์์น๊ฐ ๋ฐ๋๋ฉด์ ์์ง์ด๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ๋๋ค.
// setTimeout() ํจ์ ๋งค๊ฐ๋ณ์์ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฃ์ด์ฃผ๋ฏ์ด requestAnimationFrame๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค
requestAnimationFrame(function() {
// ๋๊ทธ๋ผ๋ฏธ์ ์์๋ฅผ ์ฐพ์์ ๋ณ์์ ์ ์ฅ
let circle = document.getElementById("circle");
// ๋๊ทธ๋ผ๋ฏธ์ ์คํ์ผ์ ๋ณ๊ฒฝํ์ฌ ์์น๋ฅผ ๋ฐ์
circle.style.left = x + "px";
circle.style.top = y + "px";
})
Animation Frames์ ์ฐ์ ์์๋ ๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์๋ค. Task Queue์ Microtask Queue๊ฐ ๋ชจ๋ ์ฒ๋ฆฌ๋ ํ์ ์คํ๋ ์๋ ์๊ณ , Task Queue์ Microtask Queue ์ฌ์ด์ ์คํ๋ ์๋ ์๋ค. ์ด๋ ์ด๋ฒคํธ ๋ฃจํ์ ๋ช ์ธ๊ฐ ์ ๋ฐ์ดํธ ๋ ๋๋ง ๋จ๊ณ์์ ์ธ์ ์ฝ๋ฐฑ์ ํธ์ถํ ์ง ์ ํํ๊ฒ ์ ์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
console.log("script start");
// task queue์ ์ ์ฌ
setTimeout(function () {
console.log("setTimeout");
}, 0);
// microtask queue์ ์ ์ฌ
Promise.resolve()
.then(function () {
console.log("promise1");
})
.then(function () {
// 8. microtask ์คํ
console.log("promise2");
});
// AnimationFrame์ ์ ์ฌ
requestAnimationFrame(function () {
console.log("animation");
});
console.log("script end");
- "script start"๋ฅผ ์ถ๋ ฅ
- setTimeout ํจ์๊ฐ Task Queue์ “setTimeout” ํ์คํฌ๋ฅผ ์ถ๊ฐ
- Promise.resolve ํจ์๊ฐ MicroTask Queue์ “promise1” ํ์คํฌ๋ฅผ ์ถ๊ฐ
- requestAnimationFrame ํจ์๊ฐ Animation Frames Queue์ “animation” ํ์คํฌ๋ฅผ ์ถ๊ฐ
- "script end"๋ฅผ ์ถ๋ ฅ
- "promise1"์ ์ถ๋ ฅ
- Promise.then ํจ์๊ฐ ๋ง์ดํฌ๋กํ์คํฌ ํ์ “promise2” ํ์คํฌ๋ฅผ ์ถ๊ฐ
- "promise2"๋ฅผ ์ถ๋ ฅ
- "animation"์ ์ถ๋ ฅ
- "setTimeout"์ ์ถ๋ ฅ
์๋ฐ์คํฌ๋ฆฝํธ ์ด๋ฒคํธ ๋ฃจํ ์๊ฐํ
์ง์ ์ฝ๋๋ฅผ ์ฐ๊ณ ์กฐ์ํ์ฌ ์ ๋๋ฉ์ด์ ์ผ๋ก ๋ณผ ์ ์๋ ์๊ฐํ ์ฌ์ดํธ๊ฐ ์์ด ์๊ฐํด๋ณธ๋ค. ์ด๊ฒ์ ๊ฒ ์คํํด๋ณด๋ฉฐ ๋ธ๋ผ์ฐ์ ๋ด๋ถ์์ ๋น๋๊ธฐ ๋์์ด ์ด๋ ํ ์์๋ก ์ผ์ด๋๋์ง ์์๋ณด์.
# ์ฐธ๊ณ ์๋ฃ
[10๋ถ ํ ์ฝํก] ๋ณ๋ฏผ์ ๋ธ๋ผ์ฐ์ ์ Event Loop
https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif
https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke
https://iamsjy17.github.io/javascript/2019/07/20/how-to-works-js.html
https://meetup.nhncloud.com/posts/89
https://sculove.github.io/post/javascriptflow/