๋กœ์šฐ ๋ ˆ๋ฒจ๋กœ ์‚ดํŽด๋ณด๋Š” Node.js ์ด๋ฒคํŠธ ๋ฃจํ”„

    ๋กœ์šฐ ๋ ˆ๋ฒจ๋กœ ์‚ดํŽด๋ณด๋Š” Node.js ์ด๋ฒคํŠธ ๋ฃจํ”„


    1๋…„ ์ „, ํ•„์ž๋Š” setImmediate & process.nextTick์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๋ฉด์„œ Node.js์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„ ๊ตฌ์กฐ์— ๋Œ€ํ•ด ์‚ด์ง ์–ธ๊ธ‰ํ•œ ์ ์ด ์žˆ์—ˆ๋‹ค. ๋†€๋ž๊ฒŒ๋„ ๋…์ž ๋ถ„๋“ค์€ ์›๋ž˜ ์„ค๋ช…ํ•˜๋ ค๊ณ  ํ–ˆ๋˜ ๋ถ€๋ถ„๋ณด๋‹ค ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋” ๋งŽ์ด ๊ด€์‹ฌ์„ ์ฃผ์—ˆ๊ณ , ํ•„์ž๋Š” ๊ทธ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋งŽ์€ ์งˆ๋ฌธ์„ ๋ฐ›์•˜์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฒˆ์—๋Š” Node.js์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋กœ์šฐ ๋ ˆ๋ฒจ์˜ ๋™์ž‘์„ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

    ์ด ํฌ์ŠคํŒ…์€ 2018๋…„ 2์›” 19์ผ์— Paul Shan์ด ์ž‘์„ฑํ•œ Node.js event loop workflow & lifecycle in low level๋ฅผ ๋ฒˆ์—ญํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ์˜์—ญ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์™œ ์ด ํฌ์ŠคํŒ…์„ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜์—ˆ๋‚˜?

    ๋งŒ์•ฝ์— ์—ฌ๋Ÿฌ๋ถ„์ด ๊ตฌ๊ธ€์—์„œ node.js event loop๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๋‚˜์˜ค๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์•„ํ‹ฐํด๋“ค์€ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ์„ค๋ช…ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค. (๊ทธ๋“ค์€ ๋งค์šฐ ๊ฑฐ์‹œ์ ์œผ๋กœ๋งŒ ์ด ๊ณผ์ •์„ ๋ฌ˜์‚ฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค.)

    node js wrong event loop wdvpem

    ์œ„ ๊ทธ๋ฆผ์€ ๊ตฌ๊ธ€์—์„œ nodejs event loop๋ฅผ ๊ฒ€์ƒ‰ํ–ˆ์„ ๋•Œ ๋‚˜์˜ค๋Š” ์ด๋ฏธ์ง€๋“ค์„ ์บก์ณํ•œ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋‹ค์ˆ˜์˜ ์ด๋ฏธ์ง€ ๊ฒฐ๊ณผ๋“ค์€ ์ž˜๋ชป ๋˜์—ˆ๊ฑฐ๋‚˜ ์‹ค์ œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๊ฑฐ์‹œ์ ์œผ๋กœ๋งŒ ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์˜ ์„ค๋ช…๋“ค ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๋“ค์€ ์ข…์ข… ์ด๋ฒคํŠธ ๋ฃจํ”„์— ๋Œ€ํ•œ ์ž˜๋ชป๋œ ์ดํ•ด๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค. ์•„๋ž˜ ์„ค๋ช…ํ•  ๋ช‡๊ฐ€์ง€ ๊ฐœ๋…์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ž˜๋ชป ์•Œ๊ณ  ์žˆ๋Š” ๋ช‡๊ฐ€์ง€ ๊ฐœ๋…๋“ค์ด๋‹ค.

    ๋Œ€ํ‘œ์ ์ธ ์ž˜๋ชป๋œ ๊ฐœ๋…๋“ค

    ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„ ๋‚ด๋ถ€์— ์žˆ๋‹ค

    ๋Œ€ํ‘œ์ ์ธ ์ž˜๋ชป๋œ ๊ฐœ๋…๋“ค ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ”๋กœ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„(V8, Spider Monkey ๋“ฑ)์˜ ์ผ๋ถ€๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋‹จ์ง€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ์œ„ํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์„ ์ด์šฉํ•˜๊ธฐ๋งŒ ํ•  ๋ฟ์ด๋‹ค. (์—ญ์ฃผ: ์‹ค์ œ๋กœ V8 ์—”์ง„์—๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๋‹ค. Node.js๋‚˜ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๊ฒƒ)

    ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ํ•˜๋‚˜์˜ ์Šคํƒ ๋˜๋Š” ํ•˜๋‚˜์˜ ํ๋กœ๋งŒ ์ž‘๋™ํ•œ๋‹ค

    ๋จผ์ €, ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์ž‘์—…์„ ๋‹ด์•„๋†“๋Š” ์Šคํƒ ๊ฐ™์€ ๊ฒƒ์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๊ณผ์ •์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ(์ž๋ฃŒ๊ตฌ์กฐ์—์„œ์˜ ๊ทธ ํ ๋งž๋‹ค.)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ณต์žกํ•œ ๊ณผ์ •์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ชจ๋“  ์ฝœ๋ฐฑ์ด ๋‹จ ํ•˜๋‚˜์˜ ํ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰๋œ๋‹ค๊ณ  ์•Œ๊ณ  ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์ž˜๋ชป๋œ ์ƒ๊ฐ์ด๋‹ค.

    ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋œ๋‹ค

    Node.js ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ž˜๋ชป๋œ ๋‹ค์ด์–ด๊ทธ๋žจ๋“ค ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ํ•œ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์„ ๋‹ด๋‹นํ•˜๊ณ  ๋‹ค๋ฅธ ํ•œ ๊ฐœ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๋‹ด๋‹นํ•˜๋Š”, ์ด ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. (ํ•„์ž๋„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‰ด๋น„ ์‹œ์ ˆ์— ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ–ˆ๋‹ค.)

    ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ๋กœ๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋กœ ์ด ๋ชจ๋“  ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

    setTimeout์€ ์ผ๋ถ€ ๋น„๋™๊ธฐ OS API์™€ ๊ด€๋ จ์žˆ๋‹ค.

    ๋˜ ๋‹ค๋ฅธ ํฐ ์˜คํ•ด๋Š” setTimeout์˜ ๋”œ๋ ˆ์ด๊ฐ€ ๋๋‚ฌ์„ ๋•Œ ์ฝœ๋ฐฑ์ด ์™ธ๋ถ€์˜ ์š”์ธ์œผ๋กœ ์ธํ•ด(OS๋‚˜ ์ปค๋„ ๊ฐ™์€) ์˜ํ•ด ์–ด๋–ค ์ž‘์—… ํ์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์ด๋Ÿฐ ์™ธ๋ถ€์˜ ์š”์ธ ๊ฐ™์€ ๊ฑด ์—†๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฐ‘์—์„œ ์ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•ด์„œ ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค.

    setImmediate์˜ ์ฝœ๋ฐฑ์€ ์ž‘์—… ํ์˜ ๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ์— ์œ„์น˜ํ•œ๋‹ค

    ๋ณดํ†ต ์ผ๋ฐ˜์ ์ธ ์ด๋ฒคํŠธ ๋ฃจํ”„์— ๋Œ€ํ•œ ์„ค๋ช…๋“ค์€ ํ•˜๋‚˜์˜ ํ๋งŒ ๊ฐ€์ง€๊ณ  ์„ค๋ช…์„ ์ง„ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ช‡๋ช‡ ๊ฐœ๋ฐœ์ž๋“ค์€ setImmediate()๊ฐ€ ์ฝœ๋ฐฑ์„ ์ž‘์—… ํ์˜ ๊ฐ€์žฅ ์•ž์ชฝ์— ๋ฐฐ์น˜ํ•˜๋Š” API๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ฒŒ ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์™„์ „ํžˆ ํ‹€๋ฆฐ ์ƒ๊ฐ์ด๋ฉฐ, ๋ชจ๋“  ์ž‘์—… ํ๋“ค์€ FIFO(First In First Out)๋กœ๋งŒ ์ž‘๋™ํ•œ๋‹ค. (์—ญ์ฃผ: ํ์— ๋“ค์–ด์žˆ๋Š” ์ž‘์—…์˜ ํฌ์ง€์…˜์„ ์ ˆ๋Œ€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ฌด์กฐ๊ฑด ํ์— ๋จผ์ € ๋“ค์–ด๊ฐ„ ์ž‘์—…์ด ๋จผ์ € ์‹คํ–‰๋œ๋‹ค.)

    ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๊ตฌ์กฐ

    ์ผ๋‹จ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ํ๋ฆ„์— ๋Œ€ํ•ด์„œ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ด๋ฏธ ํ•œ๋ฒˆ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, ๊ฑฐ์‹œ์ ์ธ ํ•˜๋‚˜์˜ ํ๋งŒ ๋ณด๋Š” ๊ฒƒ์€ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋ณ„๋กœ ๋„์›€์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ์ด ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ œ๋Œ€๋กœ ์„ค๋ช…ํ•œ ๊ทธ๋ฆผ์ด๋‹ค.

    nodejs event loop phase

    ์ด ๊ทธ๋ฆผ์— ํ‘œ๊ธฐ๋œ ๊ฐ๊ฐ์˜ ๋ฐ•์Šค๋Š” ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํŽ˜์ด์ฆˆ๋“ค์„ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ ํŽ˜์ด์ฆˆ๋Š” ๊ฐ์ž ํ•˜๋‚˜์˜ ํ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์€ ์ด ํŽ˜์ด์ฆˆ๋“ค ์ค‘ Idle, prepare ํŽ˜์ด์ฆˆ๋ฅผ ์ œ์™ธํ•œ ์–ด๋А ๋‹จ๊ณ„์—์„œ๋‚˜ ํ•  ์ˆ˜ ์žˆ๋‹ค. (์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ํ๋ผ๊ณ  ์„ค๋ช…ํ–ˆ์ง€๋งŒ ์‚ฌ์‹ค ์‹ค์ œ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ํ๊ฐ€ ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค.)

    ๊ทธ๋ฆฌ๊ณ  ์ด ๊ทธ๋ฆผ์—์„œ nextTickQueue์™€ microTaskQueue๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ๋“ค์€ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฉฐ, ์ด ํ๋“ค์— ๋“ค์–ด์žˆ๋Š” ์ž‘์—… ๋˜ํ•œ ์–ด๋–ค ํŽ˜์ด์ฆˆ์—์„œ๋“  ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์ด ํ๋“ค์— ๋“ค์–ด์žˆ๋Š” ์ž‘์—…์€ ๊ฐ€์žฅ ๋†’์€ ์‹คํ–‰ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    ์ด์ œ ์šฐ๋ฆฌ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๊ฐ์ž ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŽ˜์ด์ฆˆ๋“ค๊ณผ ํ๋“ค์˜ ์กฐํ•ฉ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด์ œ ๊ฐ๊ฐ์˜ ํŽ˜์ด์ฆˆ๊ฐ€ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ง€ ์•Œ์•„๋ณด์ž.

    Timer phase

    Timer phase๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์‹œ์ž‘์„ ์•Œ๋ฆฌ๋Š” ํŽ˜์ด์ฆˆ์ด๋‹ค. ์ด ํŽ˜์ด์ฆˆ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ์—๋Š” setTimeout์ด๋‚˜ setInterval ๊ฐ™์€ ํƒ€์ด๋จธ๋“ค์˜ ์ฝœ๋ฐฑ์„ ์ €์žฅํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ํŽ˜์ด์ฆˆ์—์„œ ๋ฐ”๋กœ ํƒ€์ด๋จธ๋“ค์˜ ์ฝœ๋ฐฑ์ด ํ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ํƒ€์ด๋จธ๋“ค์„ min-heap์œผ๋กœ ์œ ์ง€ํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ ์‹คํ–‰ํ•  ๋•Œ๊ฐ€ ๋œ ํƒ€์ด๋จธ๋“ค์˜ ์ฝœ๋ฐฑ์„ ํ์— ๋„ฃ๊ณ  ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    ์—ญ์ฃผ: ํž™(Heap)์€ ์™„์ „ ์ด์ง„ํŠธ๋ฆฌ์˜ ์ผ์ข…์œผ๋กœ ์–ด๋А ์ •๋„์˜ ๋А์Šจํ•œ ์ •๋ ฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’๋“ค์˜ ์ง‘ํ•ฉ์—์„œ ์ตœ๋Œ€ ๊ฐ’์ด๋‚˜ ์ตœ์†Œ ๊ฐ’์„ ์ฐพ์•„๋‚ด๋Š” ์ž‘์—…์— ํŠนํ™”๋˜์–ด ์žˆ๋‹ค. min-heap์€ ์ƒ์œ„ ๋ ˆ๋ฒจ์˜ ๋…ธ๋“œ๊ฐ€ ํ•˜์œ„ ๋ ˆ๋ฒจ์˜ ๋…ธ๋“œ๋“ค๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ๊ตฌ์กฐ์ด๋ฏ€๋กœ ํƒ€์ด๋จธ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผํ•˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ €์žฅํ•˜๊ธฐ์— ์•Œ๋งž๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  ํ์— ์ฝœ๋ฐฑ์„ ๋„ฃ๋Š”๋‹ค๋Š” ๊ฒƒ์€, ์ด ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ํƒ€์ด๋จธ๊ฐ€ ์ƒ์„ฑ๋˜์ง€๋งˆ์ž ํ์— ์ฝœ๋ฐฑ์„ ๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ณ„๋„์˜ ํž™์— ํƒ€์ด๋จธ๋ฅผ ์ €์žฅํ•˜๊ณ ๋‚˜์„œ ๋งค Timer phase ๋•Œ ์–ด๋–ค ํƒ€์ด๋จธ๊ฐ€ ์‹คํ–‰ํ•  ๋•Œ๊ฐ€ ๋˜์—ˆ๋Š”์ง€๋ฅผ ๊ฒ€์‚ฌํ•œ ํ›„, ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ฝœ๋ฐฑ๋งŒ ํ์— ๋„ฃ๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๊ณผ์ •์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฐ‘์—์„œ ๋‹ค์‹œ ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.

    Pending i/o callback phase

    ์ด ํŽ˜์ด์ฆˆ์—์„œ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ pending_queue์— ๋“ค์–ด์žˆ๋Š” ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค. ์ด ํ์— ๋“ค์–ด์™€์žˆ๋Š” ์ฝœ๋ฐฑ๋“ค์€ ํ˜„์žฌ ๋Œ๊ณ  ์žˆ๋Š” ๋ฃจํ”„ ์ด์ „์— ํ•œ ์ž‘์—…์—์„œ ์ด๋ฏธ ํ์— ๋“ค์–ด์™€์žˆ๋˜ ์ฝœ๋ฐฑ๋“ค์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์—ฌ๋Ÿฌ๋ถ„์ด TCP ํ•ธ๋“ค๋Ÿฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ํŒŒ์ผ์— ๋ญ”๊ฐ€๋ฅผ ์ผ๋‹ค๋ฉด TCP ํ†ต์‹ ์ด ๋๋‚˜๊ณ  ํŒŒ์ผ ์“ฐ๊ธฐ๋„ ๋๋‚˜๊ณ  ๋‚˜์„œ ํŒŒ์ผ ์“ฐ๊ธฐ์˜ ์ฝœ๋ฐฑ์ด ์ด ํ์— ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์ด๋‹ค.(ํŒŒ์ผ ์“ฐ๊ธฐ๋Š” ๋ณดํ†ต ๋น„๋™๊ธฐ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.) ๋˜ํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ์ฝœ๋ฐฑ๋„ pending_queue๋กœ ๋“ค์–ด์˜ค๊ฒŒ ๋œ๋‹ค.

    Idle, Prepare phase

    ์ด๋ฆ„์€ Idle phase์ด์ง€๋งŒ ์ด ํŽ˜์ด์ฆˆ๋Š” ๋งค Tick๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค. Prepare phase ๋˜ํ•œ ๋งค ํด๋ง(Polling)๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค. ์–ด์จŒ๋“  ์ด ๋‘๊ฐœ์˜ ํŽ˜์ด์ฆˆ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์™€ ์ง์ ‘์ ์ธ ๊ด€๋ จ์ด ์žˆ๋‹ค๊ธฐ๋ณด๋‹ค๋Š” Node.js์˜ ๋‚ด๋ถ€์ ์ธ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ํฌ์ŠคํŒ…์—์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š๋Š”๋‹ค.

    Poll phase

    ํ•„์ž๊ฐ€ ์ƒ๊ฐํ•˜๊ธฐ์— ์ „์ฒด ์ด๋ฒคํŠธ ๋ฃจํ”„ ์ค‘ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŽ˜์ด์ฆˆ๋Š” ๋ฐ”๋กœ ์ด Poll phase๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์ด ํŽ˜์ด์ฆˆ์—์„œ๋Š” ์ƒˆ๋กœ์šด ์ˆ˜์‹  ์ปค๋„ฅ์…˜(์ƒˆ๋กœ์šด ์†Œ์ผ“ ์„ค์ • ๋“ฑ)๊ณผ ๋ฐ์ดํ„ฐ(ํŒŒ์ผ ์ฝ๊ธฐ ๋“ฑ)๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ์ผ์–ด๋‚˜๋Š” ์ผ์„ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋ˆ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


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

    Check phase

    Poll phase์˜ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋Š” ๋ฐ”๋กœ setImmediate์˜ ์ฝœ๋ฐฑ๋งŒ์„ ์œ„ํ•œ ํŽ˜์ด์ฆˆ์ธ Check phase์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์–˜๊ธฐํ•˜๋ฉด ๋ณดํ†ต ํ•˜์‹œ๋Š” ์งˆ๋ฌธ์€, ์™œ setImmediate์˜ ์ฝœ๋ฐฑ๋งŒ์„ ์œ„ํ•œ ํ์ธ๊ฐ€์š”?์ด๋‹ค. ์Œ, ๊ทธ๊ฑด ๋ฐ‘์—์„œ ํ•„์ž๊ฐ€ ์›Œํฌ ํ”Œ๋กœ์šฐ ์„น์…˜์—์„œ ๋‹ค์‹œ ์–˜๊ธฐํ•  Poll phase์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ํ–‰๋™๋“ค ๋•Œ๋ฌธ์ด๊ธฐ๋„ ํ•˜๋‹ค. ์ผ๋‹จ ์ง€๊ธˆ์€ Check phase๊ฐ€ setImmediate์˜ ์ฝœ๋ฐฑ ์ „์šฉ ๋‹จ๊ณ„๋ผ๋Š” ์‚ฌ์‹ค๋งŒ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ์ž.

    Close callbacks

    socket.on('close', () => {})๊ณผ ๊ฐ™์€ close ์ด๋ฒคํŠธ ํƒ€์ž…์˜ ํ•ธ๋“ค๋Ÿฌ๋“ค์€ ์—ฌ๊ธฐ์„œ ์ฒ˜๋ฆฌ๋œ๋‹ค.

    nextTickQueue์™€ microTaskQueue

    nextTickQueue๋Š” process.nextTick() API์˜ ์ฝœ๋ฐฑ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, microTaskQueue๋Š” Resolve๋œ ํ”„๋กœ๋ฏธ์Šค์˜ ์ฝœ๋ฐฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    ์ด ๋‘๊ฐœ์˜ ํ๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ฆ‰, libUV ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌํ•จ๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ Node.js์— ํฌํ•จ๋œ ๊ธฐ์ˆ ์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ด ์นœ๊ตฌ๋“ค์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ž‘์—…๋“ค์€ ํ˜„์žฌ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ž‘์—…์ด ๋๋‚˜์ž๋งˆ์ž ํ˜ธ์ถœ๋˜์–ด์•ผํ•œ๋‹ค.

    ์—ญ์ฃผ: libUV๋Š” Node.js์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋น„๋™๊ธฐ I/O ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” C๋กœ ์ž‘์„ฑ๋˜์—ˆ๊ณ  ์œˆ๋„์šฐ๋‚˜ ๋ฆฌ๋ˆ…์Šค ์ปค๋„์„ ์ถ”์ƒํ™”ํ•ด์„œ Wrappingํ•˜๊ณ  ์žˆ๋Š” ๊ตฌ์กฐ์ด๋‹ค. ์ฆ‰, ์ปค๋„์—์„œ ์–ด๋–ค ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์„ ์ง€์›ํ•ด์ฃผ๋Š” ์ง€ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปค๋„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ๋ฐœ๊ฒฌํ•˜๋ฉด ๋ฐ”๋กœ ์ปค๋„๋กœ ์ž‘์—…์„ ๋„˜๊ฒจ๋ฒ„๋ฆฐ๋‹ค.

    ์ดํ›„ ์ด ์ž‘์—…๋“ค์ด ์ข…๋ฃŒ๋˜์–ด OS ์ปค๋„๋กœ๋ถ€ํ„ฐ ์‹œ์Šคํ…œ ์ฝœ์„ ๋ฐ›์œผ๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ OS ์ปค๋„์ด ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ž‘์—…์ผ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์— ์ž‘์—…์„ ๋˜์ ธ์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์— ๊ด€ํ•œ ๋‚ด์šฉ์€ ์›์ž‘์ž๊ฐ€ ๋ฐ‘์—์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค๋ช…ํ•˜๊ณ ์žˆ๋‹ค.

    ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ž‘์—… ํ๋ฆ„

    ์šฐ๋ฆฌ๊ฐ€ node my-script.js๋ฅผ ์ฝ˜์†”์—์„œ ์‹คํ–‰์‹œ์ผฐ์„ ๋•Œ, Node.js๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ฐ”๊นฅ์—์„œ ๋ฉ”์ธ ๋ชจ๋“ˆ์ธ my-script.js๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ํ•œ๋ฒˆ ๋ฉ”์ธ ๋ชจ๋“ˆ์ด ์‹คํ–‰๋˜๊ณ ๋‚˜๋ฉด Node.js๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ํ™œ์„ฑ ์ƒํƒœ์ธ์ง€, ์ฆ‰ ์ด๋ฒคํŠธ ๋ฃจํ”„ ์•ˆ์—์„œ ํ•ด์•ผํ•  ์ž‘์—…์ด ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค. ๋งŒ์•ฝ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๋Œ๋ฆด ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด Node.js๋Š” process.on('exit, () => {})๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ข…๋ฃŒํ•˜๋ ค๊ณ  ํ•  ๊ฒƒ์ด๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ๋Œ๋ ค์•ผํ•  ์ƒํ™ฉ์ด๋ผ๋ฉด Node.js๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ฆˆ์ธ Timer phase๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

    nodejs event loop workflow

    Timer phase

    ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ Timer phase์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋ฉด ์‹คํ–‰ํ•  ํƒ€์ด๋จธ ์ฝœ๋ฐฑ ํ์— ๋ญ๊ฐ€ ์žˆ๋Š” ์ง€ ํ™•์ธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค. ๊ทธ๋ƒฅ ํ™•์ธ์ด๋ผ๊ณ  ํ•˜๋ฉด ๊ฐ„๋‹จํ•ด๋ณด์ด์ง€๋งŒ ์‚ฌ์‹ค ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ ์ ˆํ•œ ์ฝœ๋ฐฑ๋“ค์„ ์ฐพ๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ฒŒ๋œ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ํƒ€์ด๋จธ ์Šคํฌ๋ฆฝํŠธ๋Š” ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ํž™์— ์ €์žฅ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ œ์ผ ๋จผ์ € ์ €์žฅ๋œ ํƒ€์ด๋จธ๋“ค์„ ํ•˜๋‚˜์”ฉ ๊นŒ์„œ now - registeredTime === delta ๊ฐ™์€ ์กฐ๊ฑด์„ ํ†ตํ•ด ํƒ€์ด๋จธ์˜ ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•  ์‹œ๊ฐ„์ด ๋˜์—ˆ๋Š” ์ง€ ๊ฒ€์‚ฌํ•˜๊ฒŒ ๋œ๋‹ค.(์—ญ์ฃผ: delta๋Š” setTimeout(() => {}, 10)์—์„œ์˜ 10)

    ๋งŒ์•ฝ ์กฐ๊ฑด์— ํ•ด๋‹น๋œ๋‹ค๋ฉด ์ด ํƒ€์ด๋จธ์˜ ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ํƒ€์ด๋จธ๋ฅผ ํ™•์ธํ•œ๋‹ค. ๋งŒ์•ฝ ์กฐ๊ฑด์— ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ํƒ€์ด๋จธ๋ฅผ ๋งŒ๋‚œ๋‹ค๋ฉด, ํƒ์ƒ‰์„ ๋ฐ”๋กœ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ์ด๋™ํ•œ๋‹ค. ํƒ€์ด๋จธ๋Š” ํž™ ๋‚ด๋ถ€์— ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์ดํ›„๋กœ๋Š” ํƒ์ƒ‰์„ ํ•ด๋„ ์˜๋ฏธ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์ž, ์˜ˆ๋ฅผ ๋“ค์–ด ๋”œ๋ ˆ์ด ๊ฐ’์ด 100, 200, 300, 400์ธ 4๊ฐœ์˜ ํƒ€์ด๋จธ(A, B, C, D)๋ฅผ ์–ด๋–ค ํŠน์ • ์‹œ๊ฐ„ t์— ํž™์— ๋“ฑ๋กํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

    Screen Shot 2018 02 18 at 12 50 48 PM

    ์ด์ œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ t+250์— Timer phase์— ์ง„์ž…ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

    ๊ฐ€์žฅ ๋จผ์ € ํƒ€์ด๋จธ A๋ฅผ ์ฐพ์•„๋‚ธ ํ›„ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด t+100์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ง€๊ธˆ์€ ์ด๋ฏธ t+250์ด๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ด๋จธ A์˜ ์ฝœ๋ฐฑ์€ ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํƒ€์ด๋จธ B๋ฅผ ์ฐพ์•„๋‚ด์–ด ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด t+200์ž„์„ ์ฒดํฌํ•˜๊ฒŒ๋˜๊ณ , ํƒ€์ด๋จธ B์˜ ์ฝœ๋ฐฑ ์—ญ์‹œ ์‹คํ–‰๋œ๋‹ค.

    ์ด์ œ ํƒ€์ด๋จธ C๋ฅผ ์ฒดํฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด ํƒ€์ด๋จธ์˜ ๋”œ๋ ˆ์ด๋Š” t+300์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ํŽ˜์ด์ฆˆ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ํƒ€์ด๋จธ D๋Š” ์ฒดํฌํ•˜์ง€ ์•Š๋Š”๋ฐ, ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ํƒ€์ด๋จธ๋“ค์€ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„ ์ˆœ์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ด๋จธ C์˜ ๋’ค์ชฝ์—๋Š” ์–ด์ฐจํ”ผ ํƒ€์ด๋จธ C๋ณด๋‹ค ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ๊ธด ํƒ€์ด๋จธ๋“ค๋งŒ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์ฐธ๊ณ ๋กœ ํŽ˜์ด์ฆˆ๋Š” ์‹œ์Šคํ…œ์˜ ์‹คํ–‰ ํ•œ๋„์—๋„ ์˜ํ–ฅ์„ ๋ฐ›๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์‹คํ–‰ ๋˜์–ด์•ผํ•˜๋Š” ํƒ€์ด๋จธ๊ฐ€ ์•„์ง ๋‚จ์•„ ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์‹œ์Šคํ…œ ์‹คํ–‰ ํ•œ๋„์— ๋„๋‹ฌํ•œ๋‹ค๋ฉด ๋ฐ”๋กœ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ๋œ๋‹ค.

    Pending i/o phase

    ํƒ€์ž„ ํŽ˜์ด์ฆˆ๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„ ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” Pending i/o ํŽ˜์ด์ฆˆ์— ์ง„์ž…ํ•˜๊ณ , ๊ฐ€์žฅ ๋จผ์ € ์ด์ „ ์ž‘์—…๋“ค์˜ ์ฝœ๋ฐฑ์ด ์‹คํ–‰ ๋Œ€๊ธฐ ์ค‘์ธ์ง€, ์ฆ‰ pending_queue์— ๋“ค์–ด์™€ ์žˆ๋Š”์ง€๋ฅผ ์ฒดํฌํ•˜๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ ์‹คํ–‰ ๋Œ€๊ธฐ ์ค‘์ด๋ผ๋ฉด pending_queue๊ฐ€ ๋น„๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ์˜ ์‹คํ–‰ ํ•œ๋„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๊ณ  ์žˆ๋˜ ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค. ์ด ๊ณผ์ •์ด ์ข…๋ฃŒ๋˜๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” Idle Handler Phase๋กœ ์ด๋™ํ•˜๊ฒŒ ๋œ ํ›„ ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ Prepare phase๋ฅผ ๊ฑฐ์ณ ์ตœ์ข…์ ์œผ๋กœ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋‹จ๊ณ„์ธ Poll Phase์— ๋„๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค.

    Poll phase

    ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด ํŽ˜์ด์ฆˆ๋Š” ํด๋งํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ Poll phase์— ๋“ค์–ด์™”์„ ๋•Œ watcher_queue ๋‚ด๋ถ€์— ํŒŒ์ผ ์ฝ๊ธฐ์˜ ์‘๋‹ต ์ฝœ๋ฐฑ, HTTP ์‘๋‹ต ์ฝœ๋ฐฑ ๊ฐ™์ด ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ž‘์—…๋“ค์ด ์žˆ๋‹ค๋ฉด ์ด ์ž‘์—…๋“ค์„ ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๊ณผ์ • ๋˜ํ•œ watcher_queue๊ฐ€ ๋น„๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ์˜ ์‹คํ–‰ ํ•œ๋„ ์ดˆ๊ณผ์— ๋‹ค๋‹ค๋ฅผ ๋•Œ๊นŒ์ง€ ๊ณ„์† ๋œ๋‹ค.

    ๋งŒ์•ฝ ๋” ์ด์ƒ ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ๊ฐ€ ๋œ๋‹ค๋ฉด ๋งŒ์•ฝ check_queue, pending_queue, closing_callbacks_queue์— ํ•ด์•ผํ•  ์ž‘์—…์ด ์žˆ๋Š”์ง€๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ , ๋งŒ์•ฝ ํ•ด์•ผํ•  ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด ๋ฐ”๋กœ Poll phase๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค. ํ•˜์ง€๋งŒ ํŠน๋ณ„ํžˆ ํ•ด์•ผํ•  ์ž‘์—…์ด ๋” ์ด์ƒ ์—†๋Š” ๊ฒฝ์šฐ Poll phase๋Š” ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๊ณ  ๊ณ„์† ๋Œ€๊ธฐํ•˜๊ฒŒ ๋œ๋‹ค.

    ์ด๋•Œ๋„ ๋งˆ๋ƒฅ ๋ฌดํ•œ ๋Œ€๊ธฐ๋ฅผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ , ํƒ€์ด๋จธ ํž™์—์„œ ์ฒซ๋ฒˆ์งธ ํƒ€์ด๋จธ๋ฅผ ๊บผ๋‚ด๋ณธ ๋‹ค์Œ์— ๋งŒ์•ฝ ํ•ด๋‹น ํƒ€์ด๋จธ๊ฐ€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ผ๋ฉด ๊ทธ ํƒ€์ด๋จธ์˜ ๋”œ๋ ˆ์ด ์‹œ๊ฐ„๋งŒํผ๋งŒ ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ๊ฒฐ์ •ํ•œ๋‹ค.

    ์—ญ์ฃผ: ๊ฒฐ๊ตญ Poll phase์—์„œ ๋” ์ด์ƒ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์ด ์—†๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๋Š” ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    1. Check phase์— ์‹คํ–‰ํ•  ์ฝœ๋ฐฑ์ด ์žˆ๋ƒ? ๋ฐ”๋กœ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๊ณ ๊ณ 
    2. Check phase์—๋„ ์‹คํ–‰ํ•  ์ฝœ๋ฐฑ์ด ์—†์–ด? ๊ทธ๋Ÿผ ํƒ€์ด๋จธ๋Š” ์žˆ์–ด? ์žˆ๋‹ค๋ฉด ๊ทธ ํƒ€์ด๋จธ๋ฅผ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์ด ๋  ๋•Œ๊นŒ์ง€๋งŒ ๋Œ€๊ธฐํ•˜๊ณ  ๋ฐ”๋กœ Timer phase๋กœ ๊ณ ๊ณ 
    3. ์—†์–ด? ๊ทธ๋Ÿผ ์ผ ์ƒ๊ธธ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐโ€ฆ

    2๋ฒˆ ์กฐ๊ฑด์—์„œ ํƒ€์ด๋จธ๊ฐ€ ์žˆ๋‹ค๊ณ  ๋ฐ”๋กœ Timer phase๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๊ณ  ๋Œ€๊ธฐํ•˜๋Š” ์ด์œ ๋Š”, ๋Œ€๊ธฐํ•˜์ง€์•Š๊ณ  ๋ฐ”๋กœ Timer phase๋กœ ๋„˜์–ด๊ฐˆ ๊ฒฝ์šฐ ์–ด์ฐจํ”ผ ์ฒซ๋ฒˆ์งธ ํƒ€์ด๋จธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์ด ์•ˆ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Timer phase์—์„œ๋„ ์•„๋ฌด๊ฒƒ๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  Timer phase๊ฐ€ ๋๋‚˜๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ๊ตณ์ด ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ํ•œ๋ฒˆ ๋” ๋Œ์•„์•ผ์ง€ ํ•ด๋‹น ํƒ€์ด๋จธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋˜๋ฏ€๋กœ ๊ทธ๋ƒฅ Poll phase์—์„œ ๋Œ€๊ธฐํ•˜๋Š” ๊ฒŒ ๋” ์ด๋“์ธ ๊ฒƒ์ด๋‹ค.

    Check phase

    Poll phase๊ฐ€ ์ง€๋‚˜๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋ฐ”๋กœ setImmediate() API์˜ ์ฝœ๋ฐฑ๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š” Check phase์— ๋“ค์–ด์„œ๊ฒŒ ๋œ๋‹ค. ์ด ํŽ˜์ด์ฆˆ์—์„œ๋Š” ๋‹ค๋ฅธ ํŽ˜์ด์ฆˆ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ๊ฐ€ ๋น„๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ ์‹คํ–‰ ํ•œ๋„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ณ„์† ํ•ด์„œ setImmediate์˜ ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค.

    Close callback

    Check Phase๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—, ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋‹ค์Œ ๋ชฉ์ ์ง€๋Š” close๋‚˜ destory ์ฝœ๋ฐฑ ํƒ€์ž…๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” Close callback์ด๋‹ค.

    ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ Close callback๋“ค๊ณผ ํ•จ๊ป˜ ์ข…๋ฃŒ๋˜๊ณ ๋‚˜๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋‹ค์Œ์— ๋Œ์•„์•ผํ•  ๋ฃจํ”„๊ฐ€ ์žˆ๋Š”์ง€ ๋‹ค์‹œ ์ฒดํฌ ํ•˜๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ ์•„๋‹ˆ๋ผ๋ฉด ๊ทธ๋Œ€๋กœ ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ข…๋ฃŒ๋œ๋‹ค. ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ๋” ์ˆ˜ํ–‰ํ•ด์•ผํ•  ์ž‘์—…๋“ค์ด ๋‚จ์•„ ์žˆ๋‹ค๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋‹ค์Œ ์ˆœํšŒ๋ฅผ ๋Œ๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  ๋‹ค์‹œ Timer Phase๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

    ์•„๊นŒ ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋˜ Timer Phase์—์„œ์˜ ์˜ˆ์‹œ๋ฅผ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค์ž๋ฉด, ์ด์ œ ๋‹ค์Œ ๋ฃจํ”„์˜ Timer Phase์—์„œ๋Š” ํƒ€์ด๋จธ C์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์ด ๊ฒฝ๊ณผํ–ˆ๋Š”์ง€๋ถ€ํ„ฐ ํ™•์ธ์„ ์‹œ์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

    nextTickQueue & microTaskQueue

    ๊ทผ๋ฐ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹Œ ์ด ๋‘ ํ์— ๋“ค์–ด์žˆ๋Š” ์ฝœ๋ฐฑ๋“ค์€ ์–ธ์ œ ์‹คํ–‰๋˜๋Š” ๊ฑธ๊นŒ? ์ด ๋‘ ํ์˜ ์ฝœ๋ฐฑ๋“ค์€ ์–ด๋–ค ํŽ˜์ด์ฆˆ์—์„œ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „์— ์ž์‹ ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ฝœ๋ฐฑ๋“ค์„ ์ตœ๋Œ€ํ•œ ๋นจ๋ฆฌ ์‹คํ–‰ํ•ด์•ผํ•˜๋Š” ์—ญํ• ์„ ๋งก๊ณ  ์žˆ๋‹ค.(์—ญ์ฃผ: ํŽ˜์ด์ฆˆ์—์„œ ๋‹ค๋ฅธ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ณผ์ •์„ Tick์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.)

    ๋‹ค๋ฅธ ํŽ˜์ด์ฆˆ๋“ค๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์ด ๋‘ ํ๋Š” ์‹œ์Šคํ…œ ์‹คํ–‰ ํ•œ๋„ ์ดˆ๊ณผ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Node.js๋Š” ์ด ํ๊ฐ€ ์™„์ „ํžˆ ๋น„์›Œ์งˆ ๋•Œ๊นŒ์ง€ ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  nextTickQueue๋Š” microTaskQueue๋ณด๋‹ค๋Š” ๋†’์€ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    Thread-pool

    ํ•„์ž๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ฐ€์žฅ ๋งŽ์ด ๋“ค์€ ๋‹จ์–ด๋Š” ๋ฐ”๋กœ ์Šค๋ ˆ๋“œํ’€(ThreadPoll)์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด์™€ ๊ด€๋ จ๋œ ๊ฐ€์žฅ ํฐ ์˜คํ•ด๋Š” ๋ฐ”๋กœ Node.js๊ฐ€ ๋ชจ๋“  ๋น„๋™๊ธฐ ๋ช…๋ น์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œํ’€์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์Šค๋ ˆ๋“œํ’€์€ Node.js๊ฐ€ ์•„๋‹ˆ๋ผ Node.js๊ฐ€ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ libUV์— ํฌํ•จ๋œ ๊ธฐ๋Šฅ์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

    ํ•„์ž๊ฐ€ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ๋‹ค์ด์–ด๊ทธ๋žจ์— ์Šค๋ ˆ๋“œํ’€์„ ๋ณ„๋„๋กœ ํ‘œ์‹œํ•˜์ง€ ์•Š์€ ์ด์œ ๋Š” ์Šค๋ ˆ๋“œํ’€ ์ž์ฒด๊ฐ€ ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋งค์ปค๋‹ˆ์ฆ˜์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. libUV๋Š” OS์ปค๋„์˜ ๋น„๋™๊ธฐ API๋งŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ ๋“œ๋ฆฌ๋ธ์„ ์œ ๋„ํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ถฉ๋ถ„ํžˆ ํ›Œ๋ฅญํ•˜๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŒŒ์ผ ์ฝ๊ธฐ, DNS Lookup ๋“ฑ OS ์ปค๋„์ด ๋น„๋™๊ธฐ API๋ฅผ ์ง€์›ํ•˜์ง€์•Š๋Š” ์ž‘์—…๋“ค์˜ ๊ฒฝ์šฐ์—๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œํ’€์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋•Œ ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ 4๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •๋˜์–ด์žˆ๋‹ค. uv_threadpool ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ๋Œ€ 128๊ฐœ๊นŒ์ง€ ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋ฅผ ๋Š˜๋ฆด ์ˆ˜๋„ ์žˆ๋‹ค.

    Workflow with examples

    ์ด์ œ ์ด ๋™๊ธฐ์‹ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์ž‘๋™ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์–ผ๋งˆ๋‚˜ ํฐ ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ๋Š” ์ง€ ์ดํ•ดํ–ˆ๊ธฐ ๋ฐ”๋ž€๋‹ค. ์ด ๊ตฌ์กฐ๋Š” ํ•œ๋ฒˆ์— ๋‹จ ํ•œ๊ฐœ์˜ ์ž‘์—…๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์ง€๋งŒ ๊ทธ ์–ด๋–ค ๊ฒƒ๋„ ๋ธ”๋กœํ‚นํ•˜์ง€ ์•Š๋Š”๋‹ค. ์–ด์จŒ๋“  ๋ฐฑ๋ฌธ์ด๋ถˆ์—ฌ์ผ๊ฒฌ์ด๋‹ˆ, ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์œผ๋กœ ์ด ๊ตฌ์กฐ๋ฅผ ๋‹ค์‹œ ์ดํ•ดํ•ด๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด๋„๋ก ํ•˜์ž.

    Snippet 1 โ€“ ๊ธฐ์ดˆ ์ดํ•ด

    setTimeout(() => {
        console.log('setTimeout');
    }, 0);
    setImmediate(() => {
      console.log('setImmediate');
    });

    ์œ„ ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๊ฒ ๋Š”๊ฐ€? ์•„๋งˆ๋„ ์—ฌ๋Ÿฌ๋ถ„์€ setTimeout์ด ๋จผ์ € ์ถœ๋ ฅ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ฒ ์ง€๋งŒ, ์‚ฌ์‹ค ์žฅ๋‹ดํ•  ์ˆ˜ ์—†๋‹ค.

    ์™œ๋ƒ? ๋ฉ”์ธ ๋ชจ๋“ˆ์ด ์‹คํ–‰๋˜๊ณ ๋‚˜์„œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ Timer phase์— ์ง„์ž…ํ•  ๋•Œ ์—ฌ๋Ÿฌ๋ถ„์˜ ํƒ€์ด๋จธ๋ฅผ ์ฐพ์„ ์ˆ˜๋„ ์žˆ๊ณ  ๋ชป ์ฐพ์„ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์™œ๋ƒ๋ฉด ํƒ€์ด๋จธ๋Š” ์‹œ์Šคํ…œ์˜ ์‹œ๊ฐ„๊ณผ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ์‹œ๊ฐ„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. setTimeout์ด ํ˜ธ์ถœ๋œ ์ˆœ๊ฐ„, ํƒ€์ด๋จธ๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์ด ํƒ€์ด๋จธ๋ฅผ ์ €์žฅํ•˜๊ฒŒ๋˜๋Š”๋ฐ, ๊ทธ ์ˆœ๊ฐ„ ์ปดํ“จํ„ฐ์˜ ์„ฑ๋Šฅ์ด๋‚˜ Node.js๊ฐ€ ์•„๋‹Œ ์™ธ๋ถ€ ์ž‘์—… ๋•Œ๋ฌธ์— ์•ฝ๊ฐ„์˜ ๋”œ๋ ˆ์ด๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ๋˜ ๋‹ค๋ฅธ ํฌ์ธํŠธ๋Š” Node.js๊ฐ€ Timer phase์— ์ง„์ž…ํ•˜๊ธฐ ์ „์— ๋ณ€์ˆ˜ now๋ฅผ ์„ ์–ธํ•˜๊ณ  ๊ทธ ๋ณ€์ˆ˜ now๋ฅผ ํ˜„์žฌ ์‹œ๊ฐ„์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ •ํ™•ํ•œ ๊ณ„์‚ฐ์ด๋ผ๊ณ  ํ•˜๊ธฐ์—๋Š” ์•ฝ๊ฐ„์˜ ๋…ธ์ด์ฆˆ๊ฐ€ ๊ปด์žˆ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ์ด๊ฒŒ ๋ฐ”๋กœ setTimeout์ด ๋ฐ˜๋“œ์‹œ ๋จผ์ € ์‹คํ–‰๋  ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์—†๋Š” ๋ถˆํ™•์‹ค์„ฑ์˜ ์ด์œ ๊ฐ€ ๋œ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ์ด ์ฝ”๋“œ๋ฅผ I/O ์‚ฌ์ดํด์˜ ๋‚ด๋ถ€๋กœ ์˜ฎ๊ธด๋‹ค๋ฉด, ๋ฐ˜๋“œ์‹œ setTimeout๋ณด๋‹ค setImmediate๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

    fs.readFile('my-file-path.txt', () => {
      setTimeout(() => {
        console.log('setTimeout');
      }, 0);
      setImmediate(() => {
        console.log('setImmediate');
      });
    });

    ์—ญ์ฃผ: ์œ„ ์Šค๋‹ˆํŽซ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์‹คํ–‰๋œ๋‹ค.

    1. fs.readFile์„ ๋งŒ๋‚˜๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” libUV์—๊ฒŒ ํ•ด๋‹น ์ž‘์—…์„ ๋˜์ง.
    2. ํŒŒ์ผ ์ฝ๊ธฐ๋Š” OS ์ปค๋„์—์„œ ๋น„๋™๊ธฐ API๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— libUV๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์— ํ•ด๋‹น ์ž‘์—…์„ ๋˜์ง
    3. ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” Pending i/o callback phase์˜ pending_queue์— ์ž‘์—…์˜ ์ฝœ๋ฐฑ์„ ๋“ฑ๋ก
    4. ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ Pending i/o callback phase๋ฅผ ์ง€๋‚  ๋•Œ ํ•ด๋‹น ์ฝœ๋ฐฑ์„ ์‹คํ–‰
    5. setTimeout์ด Timer phase์˜ ํ์— ๋“ฑ๋ก๋จ. ํ•ด๋‹น ์ฝœ๋ฐฑ์€ ๋‹ค์Œ Timer phase ๋•Œ ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.
    6. setImmediate์˜ ์ฝœ๋ฐฑ์ด Check phase์˜ check_queue์— ๋“ฑ๋ก๋จ.
    7. Poll phase์—์„œ๋Š” ๋”ฑํžˆ ํ•  ์ผ์ด ์—†์ง€๋งŒ, Check phase์˜ ํ์— ์ž‘์—…์ด ์žˆ์œผ๋ฏ€๋กœ ๋ฐ”๋กœ Check phase๋กœ ์ด๋™
    8. setImmediate ์ฝ˜์†” ์ถœ๋ ฅ. Timer phase์—๋Š” ํƒ€์ด๋จธ๊ฐ€ ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์‹œ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์‹œ์ž‘๋œ๋‹ค.
    9. Timer phase์—์„œ ํƒ€์ด๋จธ๋ฅผ ๊ฒ€์‚ฌ, ๋”œ๋ ˆ์ด๊ฐ€ 0์ด๋ฏ€๋กœ setTimeout์˜ ์ฝœ๋ฐฑ์„ ๋ฐ”๋กœ ์‹คํ–‰ํ•œ๋‹ค.
    10. setTimeout ์ฝ˜์†” ์ถœ๋ ฅ

    ์ฆ‰, ์ด๋Ÿฐ ๊ณผ์ •์„ ๊ฑฐ์น˜๊ธฐ ๋•Œ๋ฌธ์— setImmediate์˜ ์ฝœ๋ฐฑ์ด ๋ฐ˜๋“œ์‹œ setTimeout๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

    Snippet 2 โ€“ ํƒ€์ด๋จธ๋“ค์„ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ

    var i = 0;
    var start = new Date();
    function foo () {
        i++;
        if (i < 1000) {
            setImmediate(foo);
        } else {
            var end = new Date();
            console.log("Execution time: ", (end - start));
        }
    }
    foo();

    ์œ„์˜ ์˜ˆ์‹œ๋Š” ๊ต‰์žฅํžˆ ๊ฐ„๋‹จํ•˜๋‹ค. ํ•จ์ˆ˜ foo๋Š” setImmediate()์— ์˜ํ•ด์„œ 1000๋ฒˆ ์žฌ๊ท€ํ˜ธ์ถœ๋˜๊ณ  ์žˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ํ•„์ž์˜ ๋งฅ๋ถ ํ”„๋กœ์—์„œ Node.js 8.9.1์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ๊นŒ์ง€ 6~8ms์ •๋„๊ฐ€ ๊ฑธ๋ฆฐ๋‹ค. ์ด์ œ ์œ„์˜ ์Šค๋‹ˆํŽซ์„ setImmediate(foo)์—์„œ setTimeout(foo, 0)์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋ณด์ž.

    var i = 0;
    var start = new Date();
    function foo () {
        i++;
        if (i < 1000) {
            setTimeout(foo, 0);
        } else {
            var end = new Date();
            console.log("Execution time: ", (end - start));
        }
    }
    foo();

    ์ด์ œ ํ•„์ž์˜ ์ปดํ“จํ„ฐ์—์„œ ์ด ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ ๋Œ€๋žต 1400+ ms์ •๋„์ด๋‹ค.

    ์™œ ์ด๋ ‡๊ฒŒ ๋˜๋Š”๊ฑธ๊นŒ? ์ด ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ํด๋ง์— ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ 0์ด๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ด์•ผํ•œ๋‹ค. ๊ทผ๋ฐ ์™œ ์ด๋ ‡๊ฒŒ ์‹คํ–‰ ์‹œ๊ฐ„์ด ๋งŽ์ด ์ฐจ์ด๊ฐ€ ๋‚˜๊ฒŒ ๋œ ๊ฑธ๊นŒ?

    ๊ทธ ์ด์œ ๋Š” ๋ฐ”๋กœ ์‹œ๊ฐ„์„ ๋น„๊ตํ•˜๊ณ  ํŽธ์ฐจ๋ฅผ ์•Œ์•„๋‚ด๋Š” ์ž‘์—…์ด CPU๋ฅผ ์ง‘์ค‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํƒ€์ด๋จธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ ์ž์ฒด๋„ ์‹œ๊ฐ„์„ ์†Œ๋ชจํ•œ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด Timer phase์—์„œ๋Š” ํƒ€์ด๋จธ๋ฅผ ์‹คํ–‰ํ•  ์‹œ๊ฐ„์ด ๋˜์—ˆ๋Š”์ง€, ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ฒ€์‚ฌํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡๊ฐ€์ง€ ์ž‘์—…์„ ๊ฑฐ์ณ์•ผ ํ•˜๋Š”๋ฐ ์ด ๊ณผ์ •์„ ๋งค ์ดํ„ฐ๋ ˆ์ด์…˜๋งˆ๋‹ค ํ•˜๊ณ  ์žˆ์œผ๋‹ˆ ๋А๋ ค์งˆ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ setImmediate์˜ ๊ฒฝ์šฐ ์ด๋Ÿฐ ๊ณผ์ •์ด ํ•„์š”์—†๊ธฐ ๋•Œ๋ฌธ์— setTimeout๋ณด๋‹ค ์‹คํ–‰ ์†๋„๊ฐ€ ๋น ๋ฅธ ๊ฒƒ์ด๋‹ค.

    Snippet 3 โ€“ nextTick()๊ณผ ํƒ€์ด๋จธ ์‹คํ–‰์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ธฐ

    var i = 0;
    function foo(){
      i++;
      if(i>20){
        return;
      }
      console.log("foo");
      setTimeout(()=>{
        console.log("setTimeout");
      },0);
      process.nextTick(foo);
    }   
    setTimeout(foo, 2);

    ์œ„ ์ฝ”๋“œ์˜ ๋กœ๊ทธ๋Š” ์–ด๋–ป๊ฒŒ ์ถœ๋ ฅ๋ ๊นŒ? ์ฒซ๋ฒˆ์งธ ์ถœ๋ ฅ์€ foo๋“ค์ด ๋  ๊ฒƒ์ด๊ณ  ๊ธฐ ํ›„ setTimeout๋“ค์ด ์ถœ๋ ฅ๋œ๋‹ค. ์ œ์ผ ์ฒ˜์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด 2ms ํ›„์— ์ฒซ ๋ฒˆ์งธ foo๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ  ๋‹ค์Œ nextTickQueue์— ๋‹ค์‹œ foo()๋ฅผ ๋„ฃ๊ฒŒ๋œ๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  nextTickQueue์— ๋“ค์–ด๊ฐ„ ์ฝœ๋ฐฑ๋“ค์€ ํ•œ ํŽ˜์ด์ฆˆ์—์„œ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ๋งˆ๋‹ค ๋ฌด์กฐ๊ฑด ์ฝœ๋ฐฑ๋“ค์„ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์žฌ๊ท€ํ˜ธ์ถœ๋กœ nextTickQueue์— ๋“ค์–ด๊ฐ„ ๋ชจ๋“  ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•˜๊ณ  ๋‚˜์„œ์•ผ Timer Phase์—์„œ setTimeout ์ฝœ๋ฐฑ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

    ์ฝ”๋“œ๋ฅผ ์•ฝ๊ฐ„ ์ˆ˜์ •ํ•˜๊ณ  ๋‹ค์‹œ ์‚ดํŽด๋ณด์ž.

    var i = 0;
    function foo(){
      i++;
      if(i>20){
        return;
      }
      console.log("foo", i);
      setTimeout(()=>{
        console.log("setTimeout", i);
      },0);
      process.nextTick(foo);
    }
    
    setTimeout(foo, 2);
    setTimeout(()=>{
      console.log("Other setTimeout");
    }, 2);

    ํ•„์ž๋Š” ๊ธฐ์กด์˜ setTimeout๊ณผ ๊ฐ™์€ ๋”œ๋ ˆ์ด ์‹œ๊ฐ„์„ ๊ฐ€์ง„ setTimeout์„ ์ถ”๊ฐ€ํ–ˆ๊ณ , ์ด ํƒ€์ด๋จธ์˜ ์ฝœ๋ฐฑ์€ ๋‹จ์ง€ Other setTimeout์„ ์ถœ๋ ฅํ•˜๊ธฐ๋งŒ ํ•œ๋‹ค. ๋ญ, ํ™•์‹คํ•˜๋‹ค๊ณ  ๋งํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ ํ•œ ๊ฐœ์˜ foo๊ฐ€ ๋จผ์ € ์ถœ๋ ฅ๋œ ํ›„ Other setTimeout์ด ์ถœ๋ ฅ๋  ์ฐฌ์Šค๊ฐ€ ์กด์žฌํ•˜๊ธด ํ•œ๋‹ค. ํƒ€์ด๋จธ๋“ค์ด ๋“ค์–ด์žˆ๋Š” ํž™ ๋‚ด๋ถ€์— ๋™์ผํ•œ ๋”œ๋ ˆ์ด๋ฅผ ๊ฐ€์ง„ ํƒ€์ด๋จธ๋“ค์€ ์–ด๋–ป๊ฒŒ๋“  ๊ทธ๋ฃนํ™”๋˜์–ด์žˆ๊ณ , nextTickQueue์˜ ์ฒดํฌ๋Š” ์ง„ํ–‰ ์ค‘์ธ ์ฝœ๋ฐฑ ๊ทธ๋ฃน์˜ ์‹คํ–‰์ด ๋๋‚œ ํ›„์—์•ผ ์ง„ํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์—ญ์ฃผ: ์ฒซ ๋ฒˆ์งธ setTimeout์˜ ์ฝœ๋ฐฑ๊ณผ ๋‘ ๋ฒˆ์จฐ setTimeout์˜ ์ฝœ๋ฐฑ์ด ์‹คํ–‰๋  ์‹œ๊ฐ„์ด ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— Timer phase์—์„œ ๋‘ ํƒ€์ด๋จธ์˜ ์ฝœ๋ฐฑ์ด ๋ชจ๋‘ ํ์— ๋“ค์–ด๊ฐ”๊ณ , ์ผ๋‹จ ํ์— ๋“ค์–ด๊ฐ”์œผ๋ฉด ์‹œ์Šคํ…œ ์‹คํ–‰ ํ•œ๋„์— ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š” ์ด์ƒ ๋ฌด์กฐ๊ฑด ํ•ด๋‹น ํŽ˜์ด์ฆˆ๊ฐ€ ๋๋‚˜๊ธฐ ์ „์— ์‹คํ–‰๋œ๋‹ค.

    ์ด๋Ÿฐ ๊ฒฝ์šฐ, foo() ๋‚ด๋ถ€์˜ process.nextTick์˜ ์ฝœ๋ฐฑ์€ Timer phase์—์„œ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ ์‹คํ–‰๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— foo๊ฐ€ ๋จผ์ € ํ•œ ๊ฐœ ์ถœ๋ ฅ๋˜๊ณ  Other setTimeout์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

    ๋ช‡ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์งˆ๋ฌธ๋“ค

    ๊ทธ๋Ÿผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์ •ํ™•ํžˆ ์–ด๋””์—์„œ ์‹คํ–‰๋˜๋Š”๊ฑด๊ฐ€์š”?

    ์ด ํฌ์ŠคํŠธ๋ฅผ ์ฒ˜์Œ ์ฝ์„ ๋•Œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ •ํ™•ํžˆ ์–ด๋””์„œ ์‹คํ–‰๋˜๋Š”์ง€ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

    ์•ž์„œ ๋งํ–ˆ๋“ฏ์ด ์ด๋ฒคํŠธ ๋ฃจํ”„ ์ž์ฒด์—์„œ V8 ๋˜๋Š” ๋‹ค๋ฅธ ์—”์ง„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์ด๋•Œ, ๋‹จ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์‹คํ–‰ ์ž์ฒด๋Š” ๋™๊ธฐ์ ์ด๊ณ , ํ˜„์žฌ ์‹คํ–‰์‹œํ‚จ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋˜ํ•œ ์ง„ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

    ์™œ ์šฐ๋ฆฌ๋Š” setTimeout(fn, 0)๊ฐ€ ์žˆ๋Š”๋ฐ๋„ setImmediate๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜์š”?

    ์ผ๋‹จ, setTimeout(fn, 0)์€ ์‹ค์งˆ์ ์œผ๋กœ 0์ด ์•„๋‹ˆ๋‹ค. ์ด๊ฑด ์‚ฌ์‹ค 1์ด๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์ด ํƒ€์ด๋จธ์˜ ๋”œ๋ ˆ์ด๋ฅผ 1ms๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ 2147483647ms๋ณด๋‹ค ํฌ๊ฒŒ ์„ค์ •ํ•˜๋ฉด ๋”œ๋ ˆ์ด๋Š” ์ž๋™์œผ๋กœ 1๋กœ ์„ธํŒ…๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— setTimeout์˜ ๋”œ๋ ˆ์ด๋ฅผ 0์œผ๋กœ ์„ค์ •ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์ด ๋”œ๋ ˆ์ด๋Š” ์ž๋™์œผ๋กœ 1์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

    ์ด๋ฏธ ์„ค๋ช…ํ–ˆ๋˜ ๋Œ€๋กœ setImmediate์„ ์‚ฌ์šฉํ•˜๋ฉด ํƒ€์ด๋จธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์ฒ˜๋Ÿผ ๋”œ๋ ˆ์ด์˜ ์‹œ๊ฐ„์ด ์ง€๋‚ฌ์ง€ ๋ญ๋‹ˆ ํ•˜๋Š” ์ถ”๊ฐ€์ ์ธ ์ฒดํฌ ๋กœ์ง์ด ํ•„์š”์—†์–ด์ง„๋‹ค. ๊ทธ๋ž˜์„œ setImmediate์€ ๋น ๋ฅธ ๊ฒƒ์ด๋‹ค. ๋˜ํ•œ setImmediate์˜ ์ฒดํฌ ์ž‘์—…์€ Poll phase ์งํ›„์— ์ˆ˜ํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— HTTP ์š”์ฒญ ์ฝœ๋ฐฑ๊ณผ ๊ฐ™์€ ๊ณณ์—์„œ ์‚ฌ์šฉ๋œ setImmediate์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ๋ฐ”๋กœ ์‹คํ–‰๋œ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์™œ setImmediate๋Š” Immediate(์ฆ‰์‹œ)๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฑด๊ฐ€์š”?

    setImmediate์™€ process.nextTick ๋ชจ๋‘ ์ด๋ฆ„์ด ์ž˜๋ชป ๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์‚ฌ์‹ค setImmediate์€ ํ•œ๋ฒˆ์˜ Tick ๋˜๋Š” ๋ฃจํ”„๊ฐ€ ๋Œ ๋•Œ๋งˆ๋‹ค ๊ด€๋ฆฌ๋˜๊ณ , nextTick์€ ํ•œ ํŽ˜์ด์ฆˆ์—์„œ ๋‹ค์Œ ํŽ˜์ด์ฆˆ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋งค Tick๋งˆ๋‹ค ์ตœ๋Œ€ํ•œ ๋นจ๋ฆฌ ํ˜ธ์ถœ๋˜๋„๋ก ์ž‘๋™ํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธฐ๋Šฅ์ ์œผ๋กœ๋Š” setImmediate์ด nextTick์ด๋ผ๋Š” ์ด๋ฆ„์ด ๋” ์ž˜ ์–ด์šธ๋ฆฌ๊ณ  nextTick์ด ์ง„์งœ๋กœ ์ฆ‰์‹œ(Immediately) ํ˜ธ์ถœ๋˜๋Š” ์นœ๊ตฌ๋‹ค. ๐Ÿ˜›

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” Block ๋  ์ˆ˜ ์žˆ๋Š” ๊ฑด๊ฐ€์š”?

    ์ด๋ฏธ ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด nextTickQueue๋Š” ์ฝœ๋ฐฑ ์‹คํ–‰์— ์žˆ์–ด์„œ ์–ด๋–ค ์ œํ•œ๋„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋งŒ์•ฝ process.nextTick()์ด ์žฌ๊ท€ ํ˜ธ์ถœ๋œ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค๋ฅธ ํŽ˜์ด์ฆˆ๋“ค์˜ ํ๊ฐ€ ์–ด๋–ค ์ฝœ๋ฐฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋“ ๊ฐ„์— ์ ˆ๋Œ€ ๊ทธ ์ž‘์—…์—์„œ ๋น ์ ธ๋‚˜์˜ค์ง€ ๋ชปํ•  ๊ฒƒ์ด๋‹ค.

    ๋งŒ์•ฝ Exit callback phase์—์„œ setTimeout์„ ํ˜ธ์ถœํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?

    ๋ญ, ํƒ€์ด๋จธ ์ž์ฒด๋Š” ์‹œ์ž‘๋  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ setTimeout์˜ ์ฝœ๋ฐฑ์€ ์ ˆ๋Œ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฏธ Node.js๊ฐ€ Exit callbacks์— ๋“ค์–ด์™€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ์ด๋ฏธ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ๋น ์ ธ๋‚˜์™”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

    ์งง์€ ์ •๋ฆฌ๋“ค


    • ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ž‘์—… ์Šคํƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค.
    • ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰์€ ์–ด๋–ค ํ์—์„œ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์™€์„œ ๋‹ค๋ฅธ ๊ณณ์—์„œ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰ ์ž์ฒด๊ฐ€ ์ด๋ฒคํŠธ ๋ฃจํ”„ ์•ˆ์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค.
    • setImmediate๋Š” ์ฝœ๋ฐฑ์„ ์ž‘์—… ํ์˜ ์•ž ์ชฝ์— ๋ฐ€์–ด๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ setImmediate ๋งŒ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ „์šฉ ํŽ˜์ด์ฆˆ์™€ ํ๊ฐ€ ์กด์žฌํ•œ๋‹ค.
    • setImmediate์€ ์‹ค์งˆ์ ์œผ๋กœ ๋‹ค์Œ ํŽ˜์ด์ฆˆ ํ˜น์€ ๋‹ค์Œ ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์ˆœํšŒ์—์„œ ์‹คํ–‰๋˜๊ณ , nextTick์ด ์˜คํžˆ๋ ค ์‹ค์งˆ์ ์œผ๋กœ ๋” ๋น ๋ฅด๊ฒŒ ์‹คํ–‰๋œ๋‹ค.
    • nextTickQueue์— ๋‹ด๊ธด ์ž‘์—…์ด ์žฌ๊ท€ ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ Node.js์˜ ์ž‘์—… ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ธ”๋กํ‚นํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฃผ์˜ํ•˜๋„๋ก ํ•˜์ž.

    ๋งˆ์น˜๋ฉฐ

    ํ•„์ž๋Š” Node.js ์ฝ”์–ด ๊ฐœ๋ฐœ ํŒ€์ด ์•„๋‹ˆ๋‹ค. ์ด ํฌ์ŠคํŒ…์— ๊ด€ํ•œ ํ•„์ž์˜ ๋ชจ๋“  ์ง€์‹์€ ์‹คํ—˜๊ณผ ๋‹ค๋ฅธ ํฌ์ŠคํŒ…๋“ค์„ ํ†ตํ•ด ์–ป์€ ๊ฒƒ์ด๋‹ค. ํ•„์ž๊ฐ€ ์ด ์ง€์‹๋“ค์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ํฐ ๋„์›€์„ ์ค€ Node.js ๊ณต์‹ ๋ฌธ์„œ์— ๊ฐ์‚ฌํ•œ๋‹ค. ๋‘ ๋ฒˆ์งธ๋กœ ๋„์›€์ด ๋งŽ์ด ๋œ ํฌ์ŠคํŠธ๋Š” Saรบl Ibarra Corretgรฉ์˜ talk on libUV ํฌ์ŠคํŒ…์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„ธ ๋ฒˆ์งธ๋กœ VoidCanvas ๋…์ž ๋ถ„๋“ค ๋•๋ถ„์— ์ด๋Ÿฐ ๊ฑด๊ฐ•ํ•œ ํ† ๋ก ๊ณผ ์‹คํ—˜, ๊ด€์ฐฐ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋œ ๊ฒƒ์— ๊ฐ์‚ฌํ•œ๋‹ค. ๐Ÿ™‚

    Evan Moon

    ๐Ÿข ๊ฑฐ๋ถ์ด์ฒ˜๋Ÿผ ์‚ด์ž

    ๊ฐœ๋ฐœ์„ ์ž˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๊ฐ€ ์•„๋‹Œ ๊ฐœ๋ฐœ์„ ์ฆ๊ธฐ๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค. ์‚ฌ์†Œํ•œ ์ƒ๊ฐ ์ •๋ฆฌ๋ถ€ํ„ฐ ํŠœํ† ๋ฆฌ์–ผ, ์‚ฝ์งˆ๊ธฐ ์ •๋„๋ฅผ ์ฃผ๋กœ ๋„์ ์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.