node.js 서버는 프로세스 안에 있는 하나의 단일 스레드(single thread)에서 실행된다. node.js 서버를 실행시키면 콜백 함수 안에 있지 않은 모든 코드인 top-level 코드들이 실행된다. 그 다음 서버 어플리케이션이 필요로 하는 모든 모듈들이 require되고 모든 콜백 이벤트가 등록된다. 마지막으로 이벤트루프가 실행된다. node.js는 이벤트 기반임으로 어플리케이션의 대부분의 일이 이벤트루프에서 처리된다.
어떤 작업들은 이벤트루프가 처리하기에 무겁다(heavy, expensive). 예를 들어 파일 처리 파일 압축, 비밀번호 hashing, DNS lookup 등이 있다. 만약 이러한 작업들이 이벤트루프에서 처리되면 스레드가 block 되어 시간이 많이 소요될 수 있다. 이렇게 이벤트루프가 block 되는 것을 방지하기 위해 node.js의 프로세스에는 스레드풀이 있다.
스레드풀은 libuv 라이브러리가 node.js에 제공하는 기능으로 네개의 스레드를 추가적으로 제공한다. 이벤트루프는 무거운 작업들을 스레풀이 처리하게끔 하여 일을 분담한다. 이벤트루프가 스레드풀에게 작업물을 할당하는 것은 자동으로 처리된다. 윈도우라면 cmd에 SET UV_THREADPOOL_SIZE=1을, 맥과 리눅스라면 터미널에 UV_THREADPOOL_SIZE=1을 입력하여 스레드풀이 사이즈를 변경할 수 있다.
const fs = require('fs');
const crypto = require('crypto');
setTimeout(() => console.log('Timer 1 finished'), 0);
setImmediate(() => console.log('Immediate 1 finished'));
const start = new Date();
//process.env.UV_THREADPOOL_SIZE = 1; //change thread pool size
fs.readFile('test-file.txt', () => {
console.log('I/O finished');
console.log('------------');
setTimeout(() => console.log('Timer 2 finished'), 0);
setTimeout(() => console.log('Timer 3 finished'), 3000);
setImmediate(() => console.log('Immediate 2 finished'));
// thread가 4개라서 4개가 비슷한 시간 동안에 수행됨
crypto.pbkdf2('password', 'salt', 100000, 1024, 'sha512', ()=>{
console.log(Date.now()-start, 'password encrypted');
})
crypto.pbkdf2('password', 'salt', 100000, 1024, 'sha512', ()=>{
console.log(Date.now()-start, 'password encrypted');
})
crypto.pbkdf2('password', 'salt', 100000, 1024, 'sha512', ()=>{
console.log(Date.now()-start, 'password encrypted');
})
crypto.pbkdf2('password', 'salt', 100000, 1024, 'sha512', ()=>{
console.log(Date.now()-start, 'password encrypted');
})
crypto.pbkdf2('password', 'salt', 100000, 1024, 'sha512', ()=>{
console.log(Date.now()-start, 'password encrypted');
})
})
console.log('Hello from the top-level code');
실행 결과
Hello from the top-level code
Timer 1 finished
Immediate 1 finished
I/O finished
------------
Immediate 2 finished
Timer 2 finished
2764 password encrypted
2799 password encrypted
2881 password encrypted
2969 password encrypted
Timer 3 finished
4840 password encrypted
위 예시를 통해 이벤트 루프의 동작 방식을 확인해 볼 수 있다. top-level 코드가 먼저 실행되고, 이후 콜백 이벤트들이 실행된다. 특히 파일 처리와 같은 I/O 이벤트가 가장 마지막으로 실행 완료되는 것을 확인할 수 있다.
crypto 모듈을 사용하여 스레드풀의 동작 방식을 확인해 보았다. 4개의 작업이 거의 동일한 시간만에 실행이 된다. 이는 스레드풀에 4개의 스레드에 의해 일어나는 현상이다.
출처
https://www.udemy.com/course/nodejs-express-mongodb-bootcamp/
'Node.js' 카테고리의 다른 글
[Node.js] HTTP 모듈을 사용하여 RESTful한 서버 만들기 (0) | 2021.08.25 |
---|---|
[Node.js] Node.js? (0) | 2021.08.24 |