Node.js는 싱글 스레드 기반의 이벤트 루프를 사용하여 비동기 작업을 효율적으로 처리합니다. 하지만 CPU 집약적인 작업, 예를 들어 복잡한 계산이나 데이터 분석 등을 처리할 때는 멀티스레딩이 필요할 수 있습니다. Node.js는 이러한 작업을 위해 Worker Threads를 제공합니다.
1. Worker Threads란
[정의와 개념]
- Threads는 Node.js에서 멀티스레딩을 구현하기 위한 모듈
- 기본적으로 Node.js는 싱글 스레드로 작동하지만, Worker Threads를 사용하면 CPU를 많이 사용하는 작업을 별도의 스레드에서 실행 가능
- 메인 이벤트 루프가 차단되지 않으면서도 성능 향상 가능
[Worker Threads 사용 이유]
- CPU 집약적인 작업 처리: 비동기 작업은 이벤트 루프에서 잘 처리되지만, 복잡한 계산이나 데이터 처리 작업은 이벤트 루프를 차단 해결 가능
- 멀티코어 CPU 활용: Worker Threads를 사용하면 멀티코어 CPU를 효과적으로 활용할 수 있어 병렬 처리 가능
2. Worker Threads 설정 및 기본 사용법
Worker Threads는 worker_threads 모듈 사용.
npm i worker_threads
[메인 스레드에서 Worker를 생성하고, Worker와 메시지를 주고 받기]
- isMainThread: 코드가 메인 스레드에서 실행 중인지 여부 확인
- Worker: 새로운 Worker 스레드 생성
- parentPort: 메인 스레드와 Worker 스레드 간에 메시지를 주고받기 위한 인터페이스
// main.js
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
console.log('메인 스레드에서 실행 중입니다.');
// Worker 생성
const worker = new Worker(__filename);
// Worker에서 메시지를 수신
worker.on('message', message => {
console.log('Worker로부터 메시지:', message);
});
// Worker로 메시지 전송
worker.postMessage('안녕하세요, Worker!');
} else {
// Worker 스레드에서 실행
parentPort.on('message', message => {
console.log('메인 스레드로부터 메시지:', message);
parentPort.postMessage('메시지를 받았습니다!');
});
}
3. Worker Threads로 CPU 집약적인 작업 처리하기
[피보나치 수열을 계산하는 CPU 집약적인 작업을 처리하기]
- 피보나치 계산: Worker 스레드에서 재귀적으로 피보나치 수열 계산
- 메인 스레드에서 Worker 실행: 메인 스레드에서는 Worker를 생성하고 결과를 비동기로 기다리기.
- Worker Threads를 사용하여 CPU 집약적인 작업을 메인 스레드와 분리하여 실행
// fibonacciWorker.js
const { parentPort } = require('worker_threads');
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Worker에서 작업 실행
parentPort.on('message', n => {
const result = fibonacci(n);
parentPort.postMessage(result);
});
// main.js
const { Worker } = require('worker_threads');
function runWorker(fibonacciNumber) {
return new Promise((resolve, reject) => {
const worker = new Worker('./fibonacciWorker.js');
worker.on('message', result => resolve(result));
worker.on('error', reject);
worker.on('exit', code => {
if (code !== 0) reject(new Error(`Worker가 종료되었습니다. 코드: ${code}`));
});
worker.postMessage(fibonacciNumber);
});
}
runWorker(40)
.then(result => console.log(`피보나치 결과: ${result}`))
.catch(err => console.error(err));
4. 메시지 전달 및 데이터 공유
- Worker Threads는 메인 스레드와 데이터를 주고받을 때 메시지 전달을 사용
- Node.js는 데이터를 JSON 직렬화 방식으로 전달하므로, 복잡한 객체나 큰 데이터를 전달할 때는 성능에 영향을 줌
[데이터 공유 방법]
- Node.js는 **SharedArrayBuffer**와 같은 기능을 제공하여 메모리 공유 가능
- Worker와 메인 스레드 간의 데이터를 효율적으로 공유 가능
// sharedBuffer.js
const { Worker, isMainThread, workerData } = require('worker_threads');
if (isMainThread) {
const buffer = new SharedArrayBuffer(1024); // 메모리를 공유할 수 있는 버퍼 생성
const worker = new Worker(__filename, { workerData: buffer }); // Worker를 생성할 때 데이터를 전달하는 방법
// 메모리 공유 예제
console.log('메인 스레드에서 작업 중...');
} else {
const buffer = workerData;
// Worker 스레드에서 공유 메모리를 사용
console.log('Worker 스레드에서 작업 중...');
}
5. Worker Threads의 장점과 주의사항
장점
- 이벤트 루프 차단 방지: Worker Threads를 사용하면 메인 이벤트 루프가 차단되지 않아 비동기 작업이 원활하게 실행
- 멀티코어 활용: Node.js는 기본적으로 싱글 스레드이지만, Worker Threads를 사용하면 멀티코어를 효과적으로 사용 가능
주의사항
- 복잡성 증가: 멀티스레딩을 사용하면 코드의 복잡성 증가
- 메모리 사용량: 각 Worker는 별도의 메모리 공간을 사용하므로 메모리 사용량이 증가 가능
- 에러 관리: Worker에서 발생하는 에러를 적절히 처리 필요
Worker Threads는 Node.js에서 CPU 집약적인 작업을 효율적으로 처리할 수 있는 강력한 도구입니다. 이벤트 루프를 차단하지 않고 멀티스레딩을 구현함으로써 성능을 크게 향상시킬 수 있습니다. 하지만 멀티스레딩의 복잡성과 메모리 사용량 증가를 잘 관리해야 합니다.
반응형
'개발정리 (nodeJS)' 카테고리의 다른 글
[nodeJS] Node.js와 Apache Kafka를 사용한 스트리밍 데이터 처리 (1) | 2024.12.03 |
---|---|
[nodeJS] Node.js에서 Bcrypt를 사용한 비밀번호 해싱 및 검증하기 (0) | 2024.11.21 |
[nodeJS] Node.js에서 재귀 함수 이해하고 활용하기 (0) | 2024.11.05 |
[nodeJS] Node.js에서 JWT를 활용한 권한 관리 및 역할 기반 접근 제어 구현하기 (0) | 2024.10.01 |
[nodeJS] Node.js에서 GraphQL 서브스크립션 구현하기 (3) | 2024.09.23 |