Node.js는 왜 싱글 스레드를 고집할까?
cleanUrl: /Node.js는-왜-싱글-스레드를-고집할까? floatFirstTOC: right
Node.js는 왜 싱글 스레드를 고집할까?
JavaScript의 실행 방식 이해하기

function third() { console.log('third'); } function second() { console.log('second'); third(); } function first() { console.log('first'); second(); } first();

first → second → third 순서로 함수가 호출되고, 호출된 순서대로 스택 구조에 따라 하나씩 실행됩니다. 함수가 실행되면 콜 스택에 쌓이고, 실행이 끝나면 스택에서 제거됩니다. 이처럼 자바스크립트는 동기적으로 작업을 처리합니다.비동기 처리와 이벤트 루프

console.log("1"); setTimeout(() => console.log("2"), 1000); console.log("3");
1 3 2

- 소스 코드의 첫 번째 라인을 읽어서 콜 스택에
console.log(”1”)함수가 추가됩니다.

- 콜 스택에 있는
console.log(”1”)이 실행되어서 1이 출력됩니다.

- 콜 스택에
setTimeout()이 추가됩니다.

setTimeout()은 Node.js API입니다. 주어진 시간 동안 대기합니다.

setTimeout()을 기다리는 동안console.log(”3”)을 콜 스택에 추가합니다.

console.log(”3”)을 실행해서 3을 출력합니다.

- 지정된 시간이 지나고 Node.js API에서
setTimeout()을 이벤트 루프의 태스크 큐로 추가합니다.

- 태스크 큐에 추가된
setTimeout()을 이벤트 루프의 각 단계를 진행하면서 콜 스택에 다시 추가합니다. 이 때, 콜 스택이 비어 있는 경우에만 추가합니다.

- 콜 스택에 추가한
setTimeout()의 콜백 함수를 실행해 2를 출력합니다.
Node.js 내부 구조

1. V8 엔진 - 자바스크립트를 빠르게 실행
setTimeout(), fs.readFile() 같은 Node.js 전용 API는 이 엔진 혼자서 처리할 수 없습니다.2. libuv - 비동기 I/O와 이벤트 루프의 핵심
- 이벤트 루프 구현
- 파일 시스템, 네트워크 요청 등 비동기 I/O 처리
- 스레드 풀 관리
const fs = require('fs'); fs.readFile('example.txt', 'utf-8', (err, data) => { console.log(data); });
fs.readFile()은 V8이 직접 처리할 수 없습니다. V8은 운영체제에 직접 접근할 수 있는 권한이 없기 때문이죠. 그래서 Node.js는 이 작업을 libuv에게 위임합니다. libuv는 백그라운드 스레드 풀 중 하나를 활용해 파일을 읽고, 작업이 끝나면 콜백을 태스크 큐에 등록합니다. 이후 이벤트 루프가 콜 스택이 비는 시점을 기다렸다가 이 콜백을 실행합니다.- 자바스크립트 코드 실행 → V8이 처리
- 비동기 I/O 요청 발생 → libuv가 스레드 풀에서 처리
- 완료 시 콜백 → 이벤트 루프가 큐에서 가져와 실행
libuv 스레드 풀
fs.readFile('bigfile.txt', () => { console.log('파일 읽기 완료'); }); for (let i = 0; i < 1e9; i++) {} // CPU 바쁜 작업 console.log('연산 완료');
정리
- Node.js는 싱글 스레드로 동작하지만, libuv와 이벤트 루프 덕분에 I/O 작업은 비동기적으로 병렬 처리됩니다.
- 이 덕분에 자바스크립트의 단일 스레드 철학을 유지하면서도 높은 처리량과 확장성을 확보할 수 있습니다.
- 결과적으로, 적은 자원으로도 효율적인 서버 운영이 가능해 API 서버에 특히 적합합니다.
참고 자료

NodeJS Event Loop파헤치기
안녕하세요! 직방 서비스개발그룹 백엔드팀 아파트파트에서 근무중인 김범준입니다. 이번 포스팅에서는 NodeJS의 Event Loop에 대한 내용을 정리해보려 합니다. 그럼 같이 시작해 볼까요?
nodejs의 내부 동작 원리 (libuv, 이벤트루프, 워커쓰레드, 비동기)
참조문서https://github.com/nodejs/nodehttps://nodejs.org/ko/docs/guides/event-loop-timers-and-nexttick/https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c이벤트루프는 nodejs 의 핵심개념인데, 열심히 파헤쳐보자. 먼저 구글에 널려있는 많은 아키텍처들은 전부 틀렸다고 한다. 이 말은 libuv의 핵심 개발자 Bert Belder 등이 했다고 참조문서에서 말한다. 아무튼 그래서 구글링을 열심히해봐도 공식문서에 부합하는 아키텍쳐 그림이 없었다. ..
blog.naver.com
Libuv 라이브러리(feat. 이벤트 루프) - 3
✏️ Node.js ➡️ 네트워크 서버 구축에 특화되어 있고, V8엔진은 기존의 인터프리터 언어인 자바스크립트를 컴파일 방식으로 처리해 빠른 속도로 작업을 수행할 수 있도록 합니다. 또한, Livub 라이브러리르 사용함으로 비동기 I/O 처리가 가능하게 해 Blocking 없이 동시 요청이 가능하다. 이전에 node.js에 대해 공부를 하고 정리를 하여 글을 올렸다. Node.js를 공부하다보니 node.js에서 필수적으로 알아야 할 것들이 적어도 2가지가 있다고 생각했다. 첫 번째는 V8엔진, 두 번째는 libuv 라이브러리였다. V8엔진이 어떻게 자바스크립트 코드를 해석하고 실행되는지 또한 정리를 했었고 이번에는 libuv라이브러리가 무엇인지, Node.js안에서 어떤 역할을 담당하고 있는것인지 알아..
[번역] 로우 레벨로 살펴보는 Node.js 이벤트 루프
1년 전, 필자는 setImmediate & process.nextTick의 차이점에 대해 설명하면서 Node.js의 이벤트 루프 구조에 대해 살짝 언급한 적이 있었다. 놀랍게도 독자 분들은 원래 설명하려고 했던 부분보다 이벤트 루프 부분에 대해서 더 많이 관심을 주었고, 필자는 그 부분에 대해서 많은 질문을 받았었다. 그래서 이번에는 Node.js의 이벤트 루프를 구성하는 로우 레벨의 동작을 자세하게 설명해보려고 한다. 이 포스팅은 2018년 2월 19일에 Paul Shan이 작성한 Node.js event loop workfl…
[node.js] single thread and libuv
node.js는 기존의 multi thread와 어떻게 다를까 ? 우리가 server side언어로 개발한 서버 프로그램은 수많은 클라이언트의 요청을 처리할 수 있어야 합니다. 기존의 java, .net, php..의 경우 multi thread 방법으로 클라이언트의 요청을 처리하였습니다. 즉 각각의 클라이언트의 요청에 스레드를 할당하여 thread에서 클라이언트의 요청을 처리하는 방식을 선택하였습니다. apacha tomcat의 경우 default thread pool size(200개)를 두어 thread pool의 thread를 사용하여 클라이언트 요청을 처리하였습니다. 하지만 위와 같은 방법은 문제점이 있는데요, 1. 클라이언트의 요청이 증가함에 따라(이를 처리하는 thread의 수가 증가) 메모..
위키독스2.3 Node.js의 기술적인 특징
2.3 Node.js의 기술적인 특징
Node.js 이전의 자바스크립트는 브라우저에서 주로 실행되는 언어였습니다. 브라우저에는 V8 같은 자바스크립트 엔진이 들어 있습니다. 언어 자체가 싱글 스레드이고, 이벤트 기반…
Row level Node : js의 동작 방식부터 libuv와 event loop까지
글을 시작함에 앞서, 본 포스트는 libuv가 C++으로만 작성되었다는 등의 잘못된 내용 등 일부를 수정하기는 하였으나 다른 분들의 포스트를 참고하였고, 그대로 가져다 쓴 부분도 적지 않습니다. 출처는 포스트의 최하단부에 따로 첨부하였습니다. Summary * javascript 자체는 싱글 스레드이다. 그러나 javascript의 런타임인 브라우저와 Node(혹은 Deno)는 각각 Worker, worker_threads 등을 지원하여 멀티 쓰레딩이 가능하다. * Node는 기본적으로 I/O 관련 작업을 멀티 쓰레드 구조로 이루어진 OS 커널 혹은 libuv의 thread pool에서 처리한다. 따라서 Node가 단순히 싱글 스레드라는 것은 기술적으론 틀린 말이다. 그렇다고 어디가서 Node는 싱글 스..
