Node.js 가 종속성을 가지는 것들
- V8 Engine (자바스크립트를 머신코드로 변환해준다. JavaScript, C++ 로 작성)
- libuv (async IO에 중점을 둔 오픈소스 라이브러리, C++ 로 작성)
-- Event loop (콜백 실행, network IO)
-- Thread pool (File IO, ...)
- HTTP-parser, c-ares, OpenSSL, zlib, ...
Thread 와 Thread pool
Node.js Process
- Node.js 는 single thread
- Node.js Application을 실행하면, 유저가 10명이든 1억명이든 Single thread 로 돌으니, blocking 없이 코드를 작성해야 한다.
Single Thread에서 일어나는 일
- 프로그램 초기화
- Top level, 즉 콜백 없는 코드가 실행됨
- 모듈들의 코드를 요구함 (http 모듈..)
- 콜백들이 등록됨 (http 호출할 때, 그 호출에 콜백이 등록되는 것)
- 이벤트 루프 실행 (중요), 여기서 만약 실행하기 무거운 task가 실행되어야 한다면? 여기서 thread pool의 개념이 필요함
-- Thread pool: Additional 4 threads(or more), 하지만 개발자가 스레드 풀에 넘기거나 할 필요는 없다. 파일시스템, 암호화, 압축, DNS lookup등, 메인 스레드를 블로킹할 수 있는 일이 이루어짐
스레드 풀은 기본적으로 4개의 스레드를 가져서, 아래 이미지처럼 4개의 스레드를 모두 사용한다면, 1개의 스레드가 필요한 작업은 후순위로 밀림을 볼 수 있다
Event Loop
이벤트 루프 시작시 각 Phases
- timer를 사용한, 타이머가 만료된 콜백들 실행 (콜백 큐에서)
- 네트워크, 파일 I/O 폴링에 관련된 콜백들 실행
- setImmediate callback 실행 (I/O 콜백 후 바로 실행되는 콜백)
- 콜백 닫기 (웹소켓 닫기 등)
Process.NextTick Queue, 다른 microtasks queue 들도 있다. 이 phase들은, 이벤트 루프가 한바퀴 돌때까지 기다리지 않고 이벤트 루프 시작부터 마지막 단계인 콜백 닫기 phase의 사이 사이에 실행된다.
이벤트 루프 1 사이클(1 틱)이 끝나고, 펜딩된 timer or I/O Task가 있는지 확인 후 프로그램을 종료할지, 다시 이벤트 루프를 돌릴지 확인한다.
아래 이미지를 참고해보면, setImmediate콜백 작동 등의 순서를 확인할 수 있음
따라서, Node.js 사용시 주의할 점
- fs, crypto, zlib 등 블로킹을 유발할 수 있는 코드에는 sync 류의 코드는 피한다
- 이벤트 루프 내에서 복잡한 계산은 피하라 (루프 내의 루프,,..)
- 큰 객체의 JSON 을 다룰땐 조심하라 (stringify 오래걸릴 수 있다)
- 복잡한 정규표현식은 피해라
댓글
댓글 쓰기