
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:
- EventEmitter (depends on when the event is fired)
- Array iteration methods like forEach
- Array sort comparator callbacks
- String replace match 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/