Skip to content

Latest commit

ย 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 

Is Node.js Multi-Threaded?

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ํ•˜์ง€ ์•Š๋„๋ก ์ž‘์—…์„ ์œ„์ž„ํ•˜๋Š” ๊ฒƒ.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์˜ฌ๋ ค์ง€๋Š” ์ž‘์—…์€ ์–ด๋””์„œ ์ง„ํ–‰๋ ๊นŒ? ์ง์›๋“ค์€ ๋ˆ„๊ตฌ์ผ๊นŒ?

๋‘ ๊ฐ€์ง€ ์˜ต์…˜์ด ์กด์žฌ.

  1. OS
  2. 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๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ์š”?