JS๋ synchronous ์ธ์ด์ธ๋ฐ node.js์์๋ ์ด๋ป๊ฒ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ ๊น?
node.js๋ js๋ฅผ ๊ธฐ๋ฐ ๋ฐํ์์ด๋ js ๋์๋ฐฉ์๋๋ก ๋์ํ ์ ๋ฐ์ ์์ง ์๋?
์ฐ์ processes vs threads
Processes
- top-level execution container (like an application)
- separate memory space
- OS๊ฐ ํด๋น ํ๋ก์ธ์ค์ ์ ํด์ง ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋นํจ.
- lot of safety
Threads
- Runs inside a process
- Every thread has a parent process that it is attached to
- a single process can have multiple threads
- Shared memory space
- all of these multiple threads share the same memory.
- you don't have to do anything to share data back and forth btw two diff threads.
- really performant
all javascript, v8, and the event loop run in one thread (called the main thread)
synchronous c++ backed methods are run in the main thread
asynchronous c++ backed methods sometimes don't run in the main thread
example: Crypto
very cpu-intensive task (does a lot of math)
https://blog.logrocket.com/a-complete-guide-to-threads-in-node-js-4fa3898fe74f/
main thread ๊ฐ ์๊ณ ์ด ํ๋์ thread๊ฐ v8 ์์ง, node apis, libuv๋ฅผ ๋์์ํด.
์ด ์ค blocking ํจ์๊ฐ ์๋ค๋ฉด ์ ์ฒด ํผํฌ๋จผ์ค์ ์ํฅ์ ๋ฏธ์นจ.
๊ทธ๋์ node.js๋ libuv ๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ค๋๋ค.
Node.js๋ libuv๋ฅผ I/O-intensiveํ ์์ ๊ณผ CPU-intensiveํ ์์ ์ ์ฌ์ฉํฉ๋๋ค.
I/O-intensiveํ ์์ ์ ์์๋ก๋ DNS ์ฟผ๋ฆฌ์ File System์ ๋ค๋ฃจ๋ ์์ ์ ๋๋ฅผ ๋ค ์ ์๊ณ , CPU-intensiveํ ์์ ์ crypto ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํ ์ํธํ ๋ฐ ํด์ฑ ์ ๋๋ฅผ ์๋ก ๋ค ์ ์์ต๋๋ค.
์ฆ, DNS ์ฟผ๋ฆฌ๋ฅผ ํตํด ํธ์คํธ๋ค์์ ip๋ก resolveํ๋ ์์ , ๋น๋๊ธฐ ํ์ผ ์ฒ๋ฆฌ, ์ํธํ ๋ฑ๋ฑ ์์ ์ ์์ด์ node.js๋ ํด๋น ์์ ๋ค์ libuv๋ฅผ ์ฌ์ฉํ์ฌ thread๋ฅผ ์ฌ์ฉํฉ๋๋ค. (thread ๊ด๋ จ ๋ด์ฉ์ ์๋์์ ์กฐ๊ธ ๋ ์์ธํ ์ค๋ช ํฉ๋๋ค.)
event loop๊ฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ค.
์ด๋ฒคํธ ๋ฃจํ๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์คํ์์ผ์ฃผ๋ libuv๋ด ์ฝ๋.
๋ ธ๋์์ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ ๋๋ง๋ค ์ด๋ฒคํธ ๋ฃจํ์ ํ ๋น๋.
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ ๋ฉ์ธ ์ฐ๋ ๋์์ ์คํ๋๊ณ , ๋ชจ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ํตํด ์ฒ๋ฆฌ๋.
์ด๋ฒคํธ ๋ฃจํ๊ฐ OS์๊ฒ ์ผ์ ์ํค๊ณ ๊ฒฐ๊ณผ๊ฐ ์ค๋น๋์๋ ์ ๋ฌ๋ฐ๋ ๋ฐฉ์.
์ด๋ฒคํธ ๋ฃจํ๋ ์ง์ฅ ์์ฌ์ ๊ฐ์. ํด๋น ์ ๋ฌด๊ฐ ์งํ๋ผ์ผํจ์ ์๋ฆฌ๊ณ ์๋ฃ ์ ๋ณด๊ณ ๋ฐ๋ ํํ.
๊ณ์ ์๋ก์ด ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๊ธฐํ๊ณ ์์ผ๋ฉฐ, ํด๋น ์ด๋ฒคํธ๊ฐ ๋ค๋ฅธ ์ฝ๋๋ฅผ blockํ์ง ์๋๋ก ์์ ์ ์์ํ๋ ๊ฒ.
๊ทธ๋ ๋ค๋ฉด ์ด๋ฒคํธ ๋ฃจํ์ ์ฌ๋ ค์ง๋ ์์ ์ ์ด๋์ ์งํ๋ ๊น? ์ง์๋ค์ ๋๊ตฌ์ผ๊น?
๋ ๊ฐ์ง ์ต์ ์ด ์กด์ฌ.
- OS
- Thread Pool
์๋ฒ์์ ํต์ ๊ฐ์ ๋คํธ์ํฌ ํ์คํฌ๋ OS๊ฐ ์ฒ๋ฆฌํจ.
ํ์ผ์์คํ ์ ํ์ฉํ์ฌ ํ์ผ์ ์ฝ๋ ํ์คํฌ ๊ฐ์ ๊ฒ๋ค์ thread pool.
libuv ๋ด์๋ ์ฌ๋ฌ๊ฐ์ ์ฐ๋ ๋๋ฅผ ๊ฐ๊ณ ์๋ thread pool ์ด๋ผ๋๊ฒ ์กด์ฌํจ (๋ฏธ๋ฆฌ ์ค๋น๋์ด ์์)
libuv๋ c++ ๊ธฐ๋ฐ์ด๋ผ ์ฐ๋ ๋๊ฐ ์กด์ฌํจ.
thread pool์ thread๋ process๋ด thread์ ๊ฐ์
v8๊ณผ ์ด๋ฒคํธ๋ฃจํ๋ฅผ ์คํํ๋ ๋ฉ์ธ ์ฐ๋ ๋๊ฐ ์๊ณ ์ถ๊ฐ๋ก ๊ฐ์ฉ ๊ฐ๋ฅํ 4๊ฐ์ thread๋ฅผ ์ ๊ณตํจ (thread pool)
์ฌ๊ธฐ์ default๊ฐ 4๊ฐ์ด๊ณ thread๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์๊ณ ์์ผ๋ฉด process.env.UV_THREADPOOL_SIZE=6; ์ ํํ๋ก thread pool์ ์ฌ์ด์ฆ๋ฅผ ์ง์ ์ง์ ํด์ค thread pool์ ํฌ๊ธฐ๋ฅผ ๋๋ ค์ฃผ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค.
๋น์ฐํ thread ํ๋๋ ํ๋ฒ์ ํ๋์ task๋ง ์ฒ๋ฆฌ ๊ฐ๋ฅํ๊ณ ์ฌ์ฌ์ฉ๋.
CPU๊ฐ ์๋ก์ด task๊ฐ ์์๋ ๋งค๋ฒ ์ฐ๋ ๋๋ฅผ ์์ฑํ๊ณ ์์ ์ ๋ง์น ๋ค ์ฐ๋ ๋๋ฅผ ์์ ์ฃผ๋ ์์ ์ ์ํด๋ ๋๊ฒ ๋ง๋ค์ด์ค.
๋น์ฅ ๊ฐ์ฉ ๊ฐ๋ฅํ ์ฐ๋ ๋๊ฐ ์๋ค๋ฉด ๊ธฐ๋ค๋ ค์ผ ํจ.
libuv๊ฐ ํน์ ์ฐ๋ ๋์ ์์ ์ ํ ๋นํ๋ฉด ํด๋น ์ฐ๋ ๋๋ ๋ ๋ฆฝ์ ์ผ๋ก ์์ ์ ์งํํจ (๋ค๋ฅธ ์ฐ๋ ๋ ํน์ ์์ ์ ์ํฅ์ ์์ค๋ค๋ ๋ป)
์์ ์ ๋ง์น๋ฉด ์ด๋ฒคํธ ๋ฃจํ๊ฐ ํด๋น ์์ ์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ callback์ ์คํํจ.
ํ์ง๋ง ๋ชจ๋ ๋น๋๊ธฐ ์์ ์ด ์ฐ๋ ๋ ํ์ ์ฌ์ฉํ์ง ์์ (์ฐ๋ ๋๋ ๋ณต์กํ๊ณ ์ ๊ณต๋๋ ๋ฆฌ์์ค๊ฐ ์ ํด์ ธ ์๊ธฐ ๋๋ฌธ์)
libuv๋ ๊ฐ๋ฅํ๋ค๋ฉด OS ์ปค๋์ ์ฌ์ฉํ๊ฒ๋ ํจ.
OS ์ปค๋์ ์ฌ์ฉํด์ ์ง์ ์ปดํจํฐ์ ํ๋์จ์ด๋ฅผ ์ฌ์ฉํ๊ฒ๋ ํจ (์ปดํจํฐ ์์ฒด ์ฐ๋ ๋๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ)
์ปค๋์ ๋ค๋ฅธ ์ปดํจํฐ์์ ํต์ ๊ฐ์ ๋คํธ์ํฌ ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ณ , ์ด๋ ๊ฒ OS์์ ์ฒ๋ฆฌํ๋ฉด ๋ ํจ์จ์ ์ธ ์์ ๋ค์ OS๋ฅผ ํตํด์ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๊ฒ. (๊ฒฐ๊ณผ์ ์ผ๋ก ์ ํด์ง ์์์ ์ฌ์ฉํ๋ ์ฐ๋ ๋ ํ์ ์์์ ์๋ผ๋ ํจ๊ณผ)
OS์์ ์ฒ๋ฆฌํ๋ ๋น๋๊ธฐ ์์ ๋ค์ ์ฐ๋ ๋ํ์ ๊ฑด๋๋ฐ๊ณ ๋ฐ๋ก ์ด๋ฒคํธ๋ฃจํ์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์๋ฆฌ๊ณ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ํ์ํ callback ํจ์๋ฅผ ์คํํจ.
JS๋ single thread๋ก synchronousํ๊ฒ ๋์ง๋ง, ๋ ธ๋๋ ๋ด๋ถ์ ์ผ๋ก ์ด๋ฐ์์ผ๋ก ์๋ํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์๊ฐ ์ฐ๋ ๋๋ฅผ ์ง์ ๋ง์ง ํ์๊ฐ ์๊ณ non-blocking I/O๊ฐ ๊ฐ๋ฅํ๊ฒ ํด์ค.
๊ทธ๋ ๋ค๋ฉด thread๋ฅผ ์ธ์ ์ฌ์ฉํ ๊น์?