싱글 스레드
Node.js는 싱글 스레드 모델을 사용하는 JavaScript 런타임입니다. 이는 Node.js가 한 번에 하나의 작업만 처리할 수 있다는 것을 의미합니다.
하지만 Node.js는 비동기 I/O를 사용하여 작업을 처리하므로, 블로킹 작업이 발생하더라도 다른 작업을 처리할 수 있습니다. 이를 통해 Node.js는 높은 처리량을 달성할 수 있습니다.
또한 Node.js는 이벤트 루프를 사용하여 비동기 작업을 처리하며, 작업이 완료되면 콜백 함수를 호출하여 결과를 반환합니다. 이러한 방식으로 Node.js는 단일 스레드에서도 많은 요청을 처리할 수 있습니다.
그러나 CPU 집약적인 작업에 대해서는 성능이 떨어질 수 있으므로, 이러한 작업을 처리하는 데에는 멀티 스레드 또는 워커 프로세스 등의 다른 방법을 사용해야 합니다.
블로킹과 언블로킹
블로킹 | 어떤 작업을 처리 시 해당 작업이 완료될 때 까지 다음 작업을 실행하지 않음
블로킹(Blocking)은 어떤 작업을 처리할 때 해당 작업이 완료될 때까지 다음 작업을 실행하지 않는 것을 말합니다. 이는 대개 입출력(I/O) 작업에서 발생하며, 파일을 읽거나 쓰거나 네트워크 연결을 통해 데이터를 받는 작업 등이 해당됩니다. 블로킹 작업은 프로그램 전체가 작업을 기다리면서 다음 작업을 실행하지 못하게 만들어, 전체 시스템 성능을 저하시킬 수 있습니다.
언블로킹 | 어떤 작업을 처리 시 해당 작업의 결과가 나오기 까지 다른 작업 수행이 가능함
반면, 언블로킹(Non-blocking)은 작업을 수행하더라도 결과가 나오기 전에 다른 작업을 수행할 수 있도록 하는 것입니다. 입출력 작업을 예로 들면, 파일을 읽는 작업을 수행할 때, 해당 작업이 완료될 때까지 다른 작업을 실행할 수 있습니다. 따라서, 언블로킹 작업은 블로킹 작업과 달리 전체 프로그램의 실행을 막지 않으므로, 전체적인 성능을 향상시키는 데에 도움이 됩니다.
Node.js는 이벤트 기반 비동기 I/O 모델을 사용하여, 언블로킹 방식으로 입출력 작업을 처리합니다. 이 방식은 노드 자체적으로 작업 큐를 사용하여 요청된 작업을 비동기적으로 처리하며, 작업이 완료될 때마다 콜백 함수를 호출하여 결과를 처리합니다. 이러한 방식으로 노드는 단일 스레드에서도 많은 I/O 작업을 처리할 수 있으며, 동시성 처리를 위해 이벤트 루프와 같은 메커니즘을 사용합니다.
이벤트 기반 비동기 I/O | 입출력 작업 시 콜백 함수를 이용해 비동기적으로 실행하는 방식
이벤트 기반 비동기 I/O란, I/O 작업을 처리할 때 콜백 함수를 이용하여 비동기적으로 실행되도록 하는 방식을 말합니다. 이 방식은 비동기적인 실행을 위해 이벤트 루프(Event Loop)라는 메커니즘을 사용합니다.
이벤트 기반 비동기 I/O에서 I/O 작업은 백그라운드 스레드에서 수행되며, 작업이 완료되면 이벤트 루프에서 지정된 콜백 함수가 실행됩니다. 이벤트 루프는 이벤트 큐(Event Queue)와 호출 스택(Call Stack)으로 구성되어 있으며, 콜백 함수는 이벤트 큐에 저장되어 호출 스택이 비어있을 때 순차적으로 실행됩니다.
이 방식은 노드(Node.js)에서 기본적으로 제공되는 I/O 처리 방식입니다. 이 방식을 사용하면 I/O 작업 중 다른 작업을 처리할 수 있기 때문에, 노드에서는 비동기 I/O를 통해 대용량 데이터 처리나 네트워크 작업 등을 효율적으로 처리할 수 있습니다.
이벤트 루프
이벤트 루프는 Node.js의 핵심 컴포넌트 중 하나로, Node.js의 비동기 I/O 처리 모델에서 중요한 역할을 담당합니다.
이벤트 루프는 Node.js의 메인 스레드에서 계속해서 돌며, I/O 작업이나 타이머 등의 이벤트를 모니터링하고 이벤트 발생 시 해당 이벤트를 처리하는 역할을 수행합니다.
이벤트 루프는 이벤트 발생 시 등록된 콜백 함수를 실행하고, 이벤트가 없는 경우에는 상시 대기 상태로 남아있습니다.
이를 '이벤트 루프 대기 상태(Event Loop Idle)' 또는 '이벤트 루프 루프(Event Loop Loop)'라고 부릅니다.
이벤트 루프의 3 단계
타이머 단계 | 시간 관련 비동기 함수 사용 시 등록
Node.js의 이벤트 루프는 크게 세 가지 단계로 나눌 수 있습니다. 먼저, 이벤트 루프는 '타이머(timer) 단계'에서 등록된 타이머를 모니터링합니다. 타이머는 setTimeout(), setInterval() 등과 같은 함수를 사용해 등록될 수 있으며, 이벤트 루프는 타이머의 시간이 다 되었을 때 해당 콜백 함수를 실행합니다.
I/O 단계 | 입출력 작업에 대한 콜백함수가 실행 → 네트워크 요청/파일 시스템 등의 작업이 해당
두 번째로, 이벤트 루프는 *'I/O 단계(I/O callbacks)'에서 I/O 작업을 수행합니다. 이 단계에서는 I/O 작업에 대한 콜백 함수들이 실행되며, 네트워크 요청이나 파일 시스템 등의 작업이 여기에 해당됩니다.
체크 단계 | setImmediate() 혹은 process.nextTick() 과 같은 함수 호출 시 등록된 콜백 실행
마지막으로, 이벤트 루프는 '체크 단계(check phase)'에서 setImmediate()를 통해 등록된 콜백 함수를 실행합니다. 이 단계에서는 주로 setImmediate()나 process.nextTick() 등의 함수를 사용해 등록된 콜백 함수가 실행됩니다.
이러한 세 단계의 처리가 끝나면, 이벤트 루프는 다시 타이머 단계로 돌아가기 때문에, 위의 단계들을 계속 반복하며 이벤트를 처리하게 됩니다. 이러한 방식으로 Node.js는 비동기 I/O 작업을 효율적으로 처리하면서도, 블로킹되는 작업 없이 동작할 수 있게 됩니다.
'백엔드 > 노드' 카테고리의 다른 글
[NodeJS] fs 모듈 : 파일 시스템에 접근 시 사용 (0) | 2023.03.07 |
---|---|
[Node.js] 태스크 큐와 이벤트 큐 (0) | 2023.03.05 |
[Node.js] 컨텍스트/ 컨텍스트 스위칭 / 컨텍스트 스위칭 오버헤드 (0) | 2023.03.04 |
[Node.js] 스레드 풀 (0) | 2023.03.04 |
[node.js] node.js 서버 환경에서 css 파일 적용하는 방법 (0) | 2022.12.27 |