nodejs의 동작 원리

소개

node.js는 자바스크립트를 활용하여 고성능의 비동기 IO를 지원하는 네트워크 어플리케이션 개발 플랫폼이다.

구글의 V8이라는 자바스크립트 엔진으로 만들어져있고 single thread를 기반으로 한다.

2009년 Ryan Dahl이 파일 업로드 진행 표시줄을 보고 파일이 얼마나 업로드되었는지 알기 위해서는 서버에 쿼리를 전송해야 한다는 점을 보고 더 쉬운 방법을 찾다가 고안해냈다.

장점

  • javascript 기반이고 개발 구조가 단순화 되어 있어 빠르게 개발 가능.
  • 배우기 쉽다.
  • 풀스택 개발 용이
  • 비동기 I/O 작업을 지원해 높은 성능
  • 확장성이 뛰어남.

내부 작동 원리 구조

Node.js는 Google의 Chrome V8 자바스크립트 엔진을 기본으로 동작한다. Single Thread 기반의 Event Loop (libuv)가 돌면서 요청을 처리하며, 시스템적으로 non-blocking io를 지원하지 않는 io 호출이 있는 경우, 이를 비동기 처리 하기 위해서 내부의 Thread pool (libio)을 별도 이용하여 처리한다.

그 위에 네트워크 프로토콜을 처리하는 socket, http 바인딩 모듈이 로드 되고, 맨 윗단에, node.js에서 제공하는 standard library (파일 핸들링, console등)이 로드 된다.

Async / Non blocking IO

동기식 IO

파일을 write하는 file write 함수를 예로 들어보면,

  1. file_write 호출
  2. 디스크에 파일 쓰기 요청
  3. 디스크가 파일을 쓰는 동안 프로그램은 멈춰 대기(blocking 상태)
  4. 파일이 다 써지만 디스크에서 리턴해 file_write 함수 다음 코드로 진행

파일을 쓰는 동안에 CPU가 사용되지 않아 비효율적이다.

비동기식 IO

  1. file_async_write 호출
  2. 파일 쓰기 요청
  3. 바로 호출될 함수(callback)를 리턴
  4. 디스크에서 파일이 다 써지면 리턴한 함수를 호출

파일 쓰기를 요청하고 바로 리턴이 오기때문에 CPU는 다른일을 하고 와도 된다.

Single Thread Model

Tomcat, JBoss 등과 같은 일반적인 웹서버는 Multi Thread 기반이다.

Multi Thread

  1. Client로부터 요청이 들어옴.
  2. Thread pool에서 미리 만들어둔 Thread를 하나 꺼내 요청을 처리함.
  3. Thread pool로 Thread를 되돌려 놓음.

이런 방식은 Client의 수와 Thread 수가 같아야 하는데, 물리적으로 생성할 수 있는 Thread의 수는 한계가 있다.

Tomcat은 최대 2000개 정도의 Thread를 생성할 수 있다고 한다.

즉, 동시에 처리 가능한 Client 수가 한계가 정해져 있다는 뜻이다.

또한, IO 효율면에서도 Client에 할당된 Thread는 IO 작업(DB, Network, File)이 있을 경우 IO 호출을 해놓고, Thread는 CPU를 사용하지 않는 대기 상태로 빠져버린다.

Single Thread

  1. 하나의 Thread만을 사용해 여러 Client로부터 오는 요청을 처리
  2. IO 작업이 있을 경우, 비동기 IO 방식으로 처리
  3. 그동안 다음 요청 처리

IO 작업이 있을 경우 앞에서 설명한 비동기 IO방식으로 IO 요청을 던져놓고, 다시 돌아와서 다른 작업을 하다가 IO 작업이 끝나면 이벤트를 받아서 처리하는 구조이다.

Thread pool

nodejs도 항상 single thread만 사용하지 않는다. 일부 IO는 OS에 따라 nonblocking function을 지원하지 않는 경우가 있어 이런 함수 호출에는 어쩔 수 없이 blocking이 발생하는데, 이 경우엔 내부적으로 thread pool을 별도로 운영해 IO 처리를 해 block 되지 않게 한다.

Multiplexing

하나의 Thread로 여러 Client의 요청을 처리하는데 Multiplexing을 사용한다. 여러 개의 socket이 동시에 연결되어 있는 상태에서 하나의 Thread는 어느 socket으로부터 메시지가 들어오는지 보다, socket에서 메시지가 들어오면, 그 메시지를 꺼내 처리한다. (epoll, kqueue, dev/poll, select 등을 사용)

NodeJS를 사용할 때

  • Async IO를 사용하기 때문에, file upload/download 같은 네트워크 streaming 서비스에 유리.
  • real time web application 같은 것도 socket.io를 이용해 쉽게 만들 수 있다.
  • Single page app 개발에 용이
  • JSON API 기반 어플리케이션
  • 가볍고 생산성이 높은 웹 개발 프레임웍을 가지고 있고, 간단한 로직을 가지고 대용량과 빠른 응답 시간을 요구하는 애플리케이션에 적절

NodeJS를 사용하지 말아야 할 때

  • CPU 작업이 많은 애플리케이션에 적당하지 않다.

nodejs 는 single thread기 때문에 request 하나를 처리할 때 cpu를 많이 사용하면 다른 요청이 지연된다.



참조

https://ko.wikipedia.org/wiki/Node.js

https://www.mindinventory.com/blog/pros-and-cons-of-node-js-web-app-development/

https://bcho.tistory.com/881

김땡땡's blog

김땡땡's blog

김땡땡