Node.js 의 쓰레딩 모델



싱글 쓰레드 이벤트 루프(libuv)


보통의 클라이언트 스크립트가 싱글 쓰레드로 동작하듯, node.js 로 싱글 쓰레드로 동작한다고 말하기는 하나, 엄밀히 말해 내부적으로는 멀티 쓰레드가 구비되어 있다. 클라이언트가 요청을 보내면 이벤트 루프 쓰레드가 요청을 받아 필요에 따라(요청의 성격에 따라) 내부의 쓰레드 풀(Internal Thread Pool)에서 대기 중인 쓰레드에 요청을 위임하여 처리하며, 필요하지 않을 때는 자신(이벤트 루프 쓰레드)이 직접 처리한다. 


이 과정은 아래와 같은 순서로 이루어진다.


1. 클라이언트가 요청을 보낸다.

2. 클라이언트의 요청이 이벤트 큐(Event Queue)에 담긴다.

3. 이벤트 루프 쓰레드(싱글 쓰레드)가 이벤트 큐에서 요청을 가져온다.

4. 이벤트 루프 쓰레드가 이벤트 큐에서 꺼낸 요청이 블로킹 IO 혹은 기타 처리에 많은 시간을 요구하는 복잡한 성격의 요청인지 확인한다.

-if: 요청이 블로킹 IO 혹은 기타 처리에 많은 시간은 요구하는 복잡한 성격의 요청(주로 파일시스템 IO, 데이터베이스, 외부 서비스 처리 등)이라면-

4.1.1. 이벤트 루프 쓰레드는 이 요청을 처리하지 않고 내부 쓰레드 풀에서 대기 중인 쓰레드에게 요청을 위임한다.

4.1.2. 요청을 위임받은 내부 쓰레드는 요청을 처리하고 이벤트 루프 쓰레드에게 응답을 전달한다.

4.1.3. 이벤트 루프 쓰레드는 응답을 요청 클라이언트에게 전달한다. (종료)

-else-

4.2.1. 요청이 논 블로킹으로 처리될 성격의 요청이라면 이벤트 루프 쓰레드는 요청을 즉각 처리한다.

4.2.1. 이벤트 루프 쓰레드는 응답을 요청 클라이언트에게 전달한다. (종료)


클라이언트의 요청은 순서대로 이벤트 큐에 쌓이며, 이벤트 루프 쓰레드는 위의 이 요청을 큐에 쌓인 순서대로, 4번 과정부터 처리한다.


여기서 알 수 있는 중요한 사실은, IO 의 의미를 엄격히 적용할 때, Node.js 는 블로킹이며, IO 처리에 있어서만 논 블로킹이다.



Node.js 쓰레딩 모델의 장점


1. 클라이언트의 동시 요청을 다루기 쉽다.

2. 프로그래밍 레벨의 동시성 처리에 관하여 고민한 필요가 없다.

3. 싱글 쓰레드 이벤트 루프 덕에 클라이언트의 요청에 대해 더 많은 쓰레드를 생성할 필요가 없다.

4. 장점 3번 으로 인해 쓰레드 관리에 대한 메모리 효율이 좋다.



Node.js 쓰레딩 모델의 주의할 점


1. 무거운 작업을 내부 쓰레드에게 위임한다고 해서 이벤트 루프 쓰레드의 처리 지연이 없는 것은 아니다. 이벤트 루프 쓰레드가 내부 쓰레드와 대화하는 부분, 즉 요청을 위임하거나 응답을(내부 쓰레드로부터) 전달받는 과정에서 CPU 인텐시브한 작업이 많다면 이벤트 루프 쓰레드의 처리는 자연히 지연된다. 그리고 이벤트 루프 쓰레드는 싱글 쓰레드이기에, 이 현상은 node.js 서버의 전체 응답 시간을 지연시킬 수 있다.

2. 이벤트 루프 쓰레드의 동작에서 에러가 발생하면 서버가 쉽게 죽어버릴 수 있다. 일반적인 클라이언트 브라우저의 스크립트가 에러를 만나면 그 자리에서 멈춰버리듯, 이벤트 루프 쓰레드도 마찬가지의 경우가 발생할 수 있다.


+ Recent posts