๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ

0. ์™œ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์•ผ?

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

 

1. Why Asynchronous, Non-Blocking IO

๊ทธ๋ ‡๋‹ค๋ฉด ์™œ non-blocking IO๊ฐ€ NodeJS์˜ ํŠน์žฅ์ ์ธ์ง€ ์•Œ์•„๋ณด์ž. ์šฐ์„ , CPU ์ฝ”์–ด์˜ ํ™œ์šฉ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด ๋จผ์ € IO์˜ ํŠน์„ฑ๊ณผ blocking, non-blockingํ•˜๋Š” ์ฝ”๋“œ๋“ค์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

1) IO in general

IO๋Š” Input/Output์˜ ์ค„์ž„๋ง์ด๋‹ค. IO ์˜๋ฏธ๋Š” ๋ฒ”์œ„์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ž‘์—…์„ ๋œปํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”๋ชจ๋ฆฌ, ์ฆ‰ RAM๊ณผ ๊ทธ ์ƒ์œ„ ๋ฉ”๋ชจ๋ฆฌ ๊ณ„์ธต๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๊ตํ™˜ ํ˜น์€ ๋””์Šคํฌ - ํ•˜๋“œ๋””์Šคํฌ ๋ฐ SSD - ์™€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ์˜๋ฏธํ•œ๋‹ค. ์–ด๋–ค IO๊ฐ€ blockingํ•˜๋Š”์ง€, non-blockingํ•˜๋Š”์ง€๋Š” ์ฃผ๋กœ ๋””์Šคํฌ ํ˜น์€ ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•  ๋•Œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ํ˜น์€ ๋Ÿฐํƒ€์ž„์ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•˜๊ธฐ๋ฅผ ๋Œ€๊ธฐํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ๊ตฌ๋ถ„๋œ๋‹ค.

2) Blocking IO

Block์€ ๋ง‰๋Š”๋‹ค๋Š” ๋œป์œผ๋กœ blocking IO๋Š” ์ง์—ญํ•˜์—ฌ IO ์ž‘์—…์‹œ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰์„ ๋ง‰๋Š”๋‹ค๋Š” ๋œป์œผ๋กœ ํ•ด์„๋  ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ œ๋กœ blockingํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋“ค์ด๋‚˜ ๋Ÿฐํƒ€์ž„๋“ค์€ ๋””์Šคํฌ๋‚˜ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ ˆ์ง€์Šคํ„ฐ๊นŒ์ง€ ๋„๋‹ฌํ•˜๋Š” ๋™์•ˆ ๊ทธ ์ค„์—์„œ ๋ช…๋ ์„ ๋” ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ๋Œ€๊ธฐํ•œ๋‹ค. ๋‚ฎ์€ ๋ ˆ๋ฒจ ๊ด€์ ์—์„œ ๋ณด๋ฉด, ์ด ์ƒํƒœ์˜ CPU ์ฝ”์–ด๋Š” busy-waiting ํ•œ๋‹ค. ์‹ค์ œ๋กœ ์–ด๋–ค ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์‹คํ–‰ ์˜๋ฏธ๊ฐ€ ์—†๋Š” idle ๋ช…๋ น์„ ๊ณ„์† ๋ฐ˜๋ณตํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ์ž๋™์ฐจ๋กœ ์น˜๋ฉด, ๊ณตํšŒ์ „ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ IO์™€ ์ƒ๊ด€ ์—†๋Š” ์ž‘์—…๋“ค๋„ IO ์ž‘์—…์ด ๋ณ‘๋ชฉ์ด ๋˜์–ด CPU ์‚ฌ์ดํด์„ ๋‚ญ๋น„ํ•˜๊ฒŒ ๋œ๋‹ค.

์‚ฌ์‹ค blocking IO๊ฐ€ ํ•ญ์ƒ CPU๋ฅผ idle ์ƒํƒœ๋กœ ๊ณตํšŒ์ „ ์‹œํ‚ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. IO ์ž‘์—…์€ ์ปดํ“จํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—…๋“ค ์ค‘ ๊ฐ€์žฅ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…๋“ค ์ค‘ ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์—, ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ์ž๋“ค, ์šด์˜์ฒด์ œ ๊ฐœ๋ฐœ์ž๋“ค๋ฟ๋งŒ ์•„๋‹ˆ๋ผ CPU ์•„ํ‚คํ…ํŠธ์™€ ์—”์ง€๋‹ˆ์–ด๋“ค๋„ IO ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•œ๋‹ค. IO ์ž‘์—…๋“ค๋กœ ์ธํ•ด ๋ณ‘๋ชฉ์ด ๋˜๋Š” ์ž‘์—…๋“ค์˜ ์„ฑ๋Šฅ์„ ์กฐ๊ธˆ์ด๋ผ๋„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ํ•˜๋“œ์›จ์–ด์ ์œผ๋กœ๋Š” ํ•˜์ดํผ์Šค๋ ˆ๋”ฉ, OS์™€ ์†Œํ”„ํŠธ์›จ์–ด์ ์œผ๋กœ๋Š” ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์ด๋‚˜ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์ด ๊ฐœ๋ฐœ๋˜์—ˆ์œผ๋ฉฐ, ๋•๋ถ„์— ์ตœ์‹  CPU์— ์ตœ์‹  ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ๋™ํ–ˆ์„ ๋•Œ ๋ฌผ๋ ค์žˆ๋Š” ์ž‘์—…์„ ๋‘๊ณ  ๋…ธ๋Š” ์ผ์€ ๊ฑฐ์˜ ์—†๋‹ค.

3) Non-Blocking IO & Asynchronous programming

Non-blocking IO ์ž‘์—…์„ ๋ง‰์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, IO ์ž‘์—…์„ ์š”์ฒญํ•œ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด๋Š” ์‹ค์ œ๋กœ๋Š” IO ์ž‘์—…์„ ์š”์ฒญํ•œ ํ›„ ๋‹ค๋ฅธ ์ž‘์—…์— ์ฝ”์–ด๋ฅผ ์–‘๋ณดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ฌ์„ฑ๋œ๋‹ค. ์–‘๋ณด๋ฅผ ํ•œ ์ž‘์—…๊ณผ ์–‘๋ณด๋ฐ›์€ ์ž‘์—… ๋‘˜ ๋‹ค ์ผ๋‹จ ์ž‘์—…์ด ์‹œ์ž‘๋˜๊ณ  ๋‚˜์„œ๋Š” ์„œ๋กœ์˜ ์ง„ํ–‰ ์ƒํ™ฉ๊ณผ ์ƒํƒœ ๊ฐ’๋“ค์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค. ์ฆ‰ ๋‘ ์ž‘์—…์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ, non-blocking IO๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ—ˆ์šฉํ•˜๋Š” ๋Ÿฐํƒ€์ž„์—์„œ๋งŒ ๋‹ฌ์„ฑ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ ๊ฐœ๋…๊ณผ ์žฅ๋‹จ์  ๋˜ํ•œ ๋‹ค์ˆ˜ ๊ณต์œ ํ•œ๋‹ค.

Non-blocking IO๋ฅผ ๋‹ฌ์„ฑํ•˜๊ณ  ๋‚˜๋ฉด ์œ„์—์„œ ์ง€์ ๋œ ์ฝ”์–ด๊ฐ€ ๋†€๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์ด ๊ฑฐ์˜ ์—†์–ด์ง„๋‹ค. IO์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋™์•ˆ CPU๋Š” ๊ณตํšŒ์ „ํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ๋จผ์ € ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ, ๊ฒฐ๊ณผ๊ฐ€ ๋„์ฐฉํ•˜๋ฉด ๋„์ฐฉํ•˜๋Š” ๋Œ€๋กœ ๊ทธ ์ž‘์—…์„ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด๊ฒƒ์ด NodeJS๊ฐ€ ์ž๋ž‘ํ•˜๋Š” IO ์ฒ˜๋ฆฌ์˜ ํšจ์œจ์„ฑ ๊ทน๋Œ€ํ™”์ด๋‹ค. NodeJS๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ V8 ์—”์ง„์˜ ๊ฐœ๋ฐœ ๋กœ๋“œ๋งต์„ ๋”ฐ๋ผ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ NodeJS๊ฐ€ ๋‚˜์™”์„ ๋•Œ๋Š” ์ฝœ๋ฐฑ ํŒจํ„ด ๋˜๋Š” EventEmitter๋ฅผ ๊ตฌ๋…(subscribe)ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฃผ๋กœ ์ผ์—ˆ๋‹ค. ์ตœ์‹  JS์—์„œ๋Š” Promise, async/await, generator, rxjs ๋ฐ ๊ธฐํƒ€ ๋น„๋™๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•˜๊ณ  ์‰ฌ์šด ๋ฐฉ๋ฒ•์œผ๋กœ ๋น„๋™๊ธฐ ๋กœ์ง์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ด๊ฒƒ์ด ๊ถŒ์žฅ๋œ๋‹ค.

 

2. Event Loop

Node js๋Š” v8์˜ ๋“ฑ์žฅ์œผ๋กœ ๋ถ€ํ„ฐ ์‹œ์ž‘๋๋‹ค. Event loop์€ V8 ๋Ÿฐํƒ€์ž„์˜ ์ŠคํŽ™์ด๋ฉฐ, ์ด๋Š” JS ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์™ธ๋ถ€์˜ ์ž๊ทน์— ๋ฐ˜์‘ํ•˜๋Š”์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค. ๋˜ํ•œ ๊ฐ€๋ฒผ์šด ๋น„๋™๊ธฐ ๋กœ์ง์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์›์ฒœ์ด๊ธฐ๋„ ํ•˜๋‹ค. ๋™๊ธฐ ์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์ด ๋๋‚˜๊ณ  ๋‚˜๋ฉด ๋ชจ๋“  ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์€ ์ผ์ข…์˜ ํ์— ๋“ค์–ด๊ฐ€๋ฉฐ, ์ž‘์—…๋“ค์ด ๋๋‚˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ํ์—์„œ ํŠ€์–ด๋‚˜์˜จ๋‹ค. ํŒŒ์ผ ์‹œ์Šคํ…œ์—์„œ ํŠน์ • ํŒŒ์ผ์„ ์ฝ์–ด์˜ค๋Š” ์ผ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ ์ดํ›„ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ผ, ํ˜น์€ ๋ฐ˜๋Œ€๋กœ ์ƒˆ๋กœ์šด ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ผ, DB์— ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ผ๋“ค ๋“ฑ IO ์ž‘์—…๋“ค์ด ๋Œ€๋ถ€๋ถ„ ์š”์ฒญ์ด ๋๋‚˜๋ฉด ํ์— ๋“ค์–ด๊ฐ„๋‹ค. Event loop๋Š” ์ด ์‹œ์ ๋ถ€ํ„ฐ ๊ณ„์† ์ˆœํšŒํ•˜๋ฉฐ ํ์— ์žˆ๋Š” ์ž‘์—…๋“ค ์ค‘ ์™„๋ฃŒ๋œ ์ž‘์—…๋“ค์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๋งŒ์•ฝ ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ์— ๋ฌผ๋ ค์žˆ๋Š” ์ฝœ๋ฐฑ๋“ค์„ ์‹คํ–‰ํ•œ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์ฝœ๋ฐฑ, Promise์˜ then ํ˜น์€ catch ์ฝœ๋ฐฑ, await ํ˜น์€ yield ์ดํ›„์˜ ์Šคํฌ๋ฆฝํŠธ๋“ค์ด๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๋“ค์ด ์—ฌ๊ธฐ์— ํ•ด๋‹น๋œ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ด๋ฒคํŠธ์˜ ์›์ฒœ์€ ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ๋˜๋Š” AJAX๋ฅผ ํ†ตํ•œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์œผ๋กœ ํ•œ์ •๋œ๋‹ค. libuv ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์ธ ๋น„๋™๊ธฐ IO ์ž‘์—…์„ ์ถ”์ƒํ™”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ , NodeJS๋Š” libuv์™€ V8์˜ event loop์„ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฒฐํ•ฉํ•˜์—ฌ JS ์Šคํฌ๋ฆฝํŠธ๋กœ ์ข€ ๋” ๋‚ฎ์€ ๋ ˆ๋ฒจ์˜ ๋„คํŠธ์›Œํฌ ์ž‘์—…์ด๋‚˜ ๋””์Šคํฌ์— ์ ‘๊ทผํ•˜๋Š” ์ž‘์—… ๋“ฑ ์ผ๋ฐ˜์ ์ธ IO ์ž‘์—…๋“ค์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ๋‹ค.

 

3. Node.js์˜ ํŠน์ง• ์š”์•ฝ

1. ์‹ฑ๊ธ€์Šค๋ ˆ๋“œ: ์Šค๋ ˆ๋“œ๊ฐ€ ๋Š˜์–ด๋‚˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ค๋ฅธ ์–ธ์–ด์˜ ์›น ์„œ๋ฒ„๋ณด๋‹ค IO ๊ด€์ ์—์„œ ๋ฆฌ์†Œ์Šค๊ด€๋ฆฌ์— ํšจ์œจ์ ์ด๋‹ค.

2. ๋น„๋™๊ธฐ: Node.js๋Š”๋น„๋™๊ธฐ ๋ฐฉ์‹์˜ ํ•จ์ˆ˜๊ฐ€ ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค. (์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ: ๋™๊ธฐ)

3. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜: ๋™์ž‘์ด ์™„๋ฃŒ๋  ๊ฒฝ์šฐ ์‹คํ–‰ํ•  ํ•จ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๋“ฑ๋กํ•œ๋‹ค.

 

=> non-blocking IO์˜ ํŠน์žฅ์ ์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด, ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ๋ฅผ ํƒํ–ˆ๊ณ  ์ด๋ฅผ ์œ„ํ•ด ๋น„๋™๊ธฐ ๋™์ž‘์ด ํ•„์š”ํ•˜์—ฌ, ๋น„๋™๊ธฐ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๊ตฌํ˜„ํ•œ๋‹ค.

โ€‹

Q. Are all Node.js callback functions asynchronous?

A. No. Only I/O is usually asynchronous, but many other callbacks are synchronous. Always check the docs.


Examples of async functions:

  • Async Filesystem access (they have sync counterparts without callbacks, though)
  • Timers (setTimeout)
  • process.nextTick, setImmediate
  • most database connections
  • network connections
  • Promises

Examples of sync callbacks:

NodeJS์˜ ๋ชจ๋“ˆ๋“ค์€ ๊ฐ™์€ API๋ฅผ asyncํ•œ ๊ฒƒ๊ณผ syncํ•œ ๊ฒƒ ๋‘ ์ข…๋ฅ˜๋ฅผ ๋ชจ๋‘ ์ œ๊ณตํ•˜๋Š”๋ฐ, syncํ•œ ์ข…๋ฅ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ event loop์˜ ์‚ฌ์ดํด์„ ๋ง‰๊ณ  ํ•ด๋‹น ์ž‘์—…๋“ค์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•œ๋‹ค. fs ๋ชจ๋“ˆ์˜ readFile๊ณผ readFileSync๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋“ค์ด ๊ทธ๋Ÿฌํ•˜๋‹ค. readFile์€ ํŒŒ์ผ์„ ์ฝ๋Š” ๋™์•ˆ ๋Œ€๊ธฐํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ํ›„, ํŒŒ์ผ ์ฝ๊ธฐ๊ฐ€ ๋๋‚˜๋ฉด ์ฝœ๋ฐฑ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๋ฐ˜๋ฉด readFileSync๋Š” ํŒŒ์ผ ์ฝ๊ธฐ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ NodeJS์˜ ๋ชจ๋“  ์ž‘์—…์„ ์ค‘๋‹จ์‹œํ‚ค๊ณ  ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

 

๋งŽ์€ ๊ณ„์‚ฐ์„ ์š”๊ตฌํ•˜๋Š” ์ž‘์—…๋“ค๋˜ํ•œ event loop์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์ด ๊ณ„์‚ฐ์„ ํ•ด์•ผ์ง€ ๋ญ˜ ๋ง‰๋‚˜? ๊ทธ๋ ‡๋‹ค. JS๋Š” ์• ์ดˆ์— ๊ทธ๋Ÿฐ ์ž‘์—…๋“ค์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ์–ธ์–ด๊ฐ€ ์•„๋‹ˆ๊ณ  NodeJS ๋˜ํ•œ ๊ทธ๋Ÿฌํ•˜๋‹ค. NodeJS ๋˜ํ•œ ๊ทธ๋Ÿฐ ์ž‘์—…๋“ค์„ JS๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ๋ชจ๋“ˆ์ด๋‚˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒดํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค. NodeJS๋Š” ์˜ค๋กœ์ง€ IO์—๋งŒ ์ง‘์ค‘ํ•ด์•ผ ํ•œ๋‹ค. ์•”ํ˜ธ, ๋ณตํ˜ธ ์—ฐ์‚ฐ์ด๋‚˜ ํ–‰๋ ฌ ์—ฐ์‚ฐ ๊ฐ™์€ CPU๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…๋“ค์€ JS ์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑ๋˜์—ˆ์„ ๋•Œ ์•„์ฃผ ๋น„ํšจ์œจ์ ์ด๋ฉฐ, ๋”์šฑ ์น˜๋ช…์ ์ธ ์ ์€ ์ด ๊ณ„์‚ฐ์ด ์ด๋ฃจ์–ด์ง€๋Š” ๋™์•ˆ event loop๊ฐ€ ๋Œ€๊ธฐํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ง์ ‘ ๋‹ค๋ฅธ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ทธ๋Ÿฐ ์ž‘์—…๋“ค์„ ๊ตฌํ˜„ํ•˜๊ณ  ์ด๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ NodeJS์™€ ์—ฐ๊ฒฐํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์œผ๋‚˜, ๋Œ€๋ถ€๋ถ„์€ ์ด๋ฏธ npm์— ๊ตฌํ˜„์ฒด๊ฐ€ ์˜ฌ๋ผ์™€ ์žˆ์„ ๊ฒƒ์ด๋‹ค. 

 

reference

https://blog.appleseed.dev/post/nodejs-non-blocking-io-and-multicore-processing/

๋ฐ˜์‘ํ˜•