node.js 는 단일 쓰레드 환경이다.

그런데 이 말은, 사용자의 스크립트가 단일 쓰레드에서 구동된다는 의미이다.

즉, 사용자의 요청들을 처리하기 위한 이벤트 루프가 하나의 쓰레드로 돌아간다.

그러나, 실제 비동기 작업(파일, 네트워크 처리등)은 멀티 쓰레드(thread pool) 로 구현된다.

blog-image

위 그림은 Jeff Kunkel 의 Node.js Explained 유튜브 동영상을 갭쳐한 것이다.

우측으로 node.js 의 쓰레드들이 잘 나타나 있다.

node.js는 비동기 작업을 위해 libuv 를 활용하는데 여기서 Thread Pool 을 만들어서 작업쓰레드 들이 요청들을 처리하게 된다.

이 상황을 음식점으로 비유를 해보면 어떨까.

중앙에 큰 홀 하나 가 있고 주방이 2개 인 식당이 있다고 가정 해보면,
node.js에서 일어나는 일은 다음과 같을 것이다.

  • 손님들이 몰려와 식당문을 열고 들어온다. 그리고 여기 저기서 주문을 한다.

  • 종업원이 돌아다니며 부른 순서대로 가서 주문을 한명씩 받고, 주문 즉시 주문내역을 재빨리 쪽지에 적어서 주방앞에 순서대로 붙여놓는다.

  • 다른 손님들 주문도 이런식으로 처리한다.

  • 모든 주문접수가 끝나면, 종업원은 또다른 손님이 주문을 하거나, 요리가 나오기만을 기다린다. 이 종업원은 멀티태스킹이 안되는 우직한 사람으로서, 오직 서빙(주문/요리 배달) 만을 처리한다.

  • 한편, 주방에서는 여러명의 요리사가 대기중이며, 쪽지를 순서대로 가져와서 각자 요리를 한다. 그런데 주방이 2개 있으니 만약 한쪽이 붐빈다면, 음식점 사장은 그중에 좀 덜 번잡스러운곳으로 가서 요리를 하라고 요리사들을 안내할것이다.

  • 요리가 먼저 준비되는 순서대로 내놓는다. 그리고 다시 주문서 하나를 가져다가 주방에서 요리를 시작한다. 홀에 있는 종업원은 요리가 나오는것을 지켜보다가 하나씩 가져와서 고객에게 전달한다.
    가지러 가는사이 다른 손님이 주문을 하려해도 이미 늦었다. 이 종업원은 이전 손님의 요리를 가져와서 먼저 서빙한후에 주문을 받으러 올것이다.

위 예에서 2개의 주방은 2 코어, 우직한 종업원은 이벤트 루프, 쪽지들은 큐, 주방의 요리사들은 작업 멀티 쓰레드 라고 볼수 있다.
우리 사장님은 커널의 위치쯤 될거 같다.
사장님이 요리사들을 2개 주방으로 분산시키는것은 바로 스케쥴러에 의해 이루어지는 작업일것이다.

이처럼 node.js 가 멀티코어를 전혀 이용 못하는 것은 아니다.
OS에 의해 스케쥴링이 이루어지며 서로 다른 core에 배정되어 동작할수 있기 때문이다 .