Node.js의 워커 스레드 with 타입스크립트

상수·2023년 10월 6일
0

흔히 Node.js는 싱글 스레드 논-블로킹으로 작동한다고 알려져 있습니다. 싱글 스레드로 작동하되, 비동기 I/O 작업을 통하여 작업을 서로 블로킹하지 않음으로서 요청을 처리합니다.

그렇지만 Node.js에서 아예 멀티 스레드를 사용할 수 있는 방법이 없지는 않습니다. Node.js 12 LTS 버전부터 포함된 워커 스레드 패키지를 사용하면 멀티 스레드를 사용할 수 있습니다.

워커 스레드 작성하기

워커 스레드 생성 코드

먼저, 워커 스레드를 생성하는 코드를 작성합니다. Worker 객체는 이벤트 기반으로 작동하지만, 메세지를 받았을 때 resolve를 하도록 작성합니다.

workerData에는 워커 스레드에 넘길 데이터를 입력합니다.

// index.ts

import path from 'node:path';
import { Worker } from 'node:worker_threads';

function bootstrap(): Promise<{}> {
  return new Promise((resolve, reject) => {
    const worker = new Worker(path.resolve(__dirname, 'service.js'), {
      workerData: {
        message: 'hello', 
        path: path.resolve(__dirname, 'service.ts'),
      }
    });
    worker.on('message', resolve);
    worker.on('error', reject);
    worker.on('exit', (code) => {
      if (code !== 0)
        reject(new Error(`Worker stopped with exit code ${code}`));
    });
  });
}

async function run() {
  const message = await bootstrap();
  console.log(message);
}

run().catch((err) => console.error(err));

스레드에서 실행할 코드 생성

워커 스레드를 생성할 때 타입스크립트 코드를 직접 읽을 수 있으면 좋겠으나… 타입스크립트 코드를 직접적으로 읽지 못합니다. 따라서 중간에서 타입스크립트 코드를 포함하는 자바스크립트 코드가 필요합니다.

워커 스레드를 생성하는 코드를 작성할 때 넘겨줄 데이터에 타입스크립트의 경로를 명시하였습니다. 받아온 경로를 이용하여 아래와 같이 자바스크립트 코드에 타입스크립트 코드를 포함시킵니다.

// service.js

const path = require('path');
const { workerData } = require('worker_threads');
 
require('ts-node').register();
require(path.resolve(__dirname, workerData.path));

이렇게 한 다음 워커 스레드에서 실행할 코드를 작성합니다. 간단한 메세지를 반환하는 코드를 작성합니다. 스레드를호출한 주체에 parentPort 를 통하여 메세지를 전송할 수 있습니다.

// service.ts

import { isMainThread, parentPort, workerData } from 'node:worker_threads';

function run() {
  if (!isMainThread) {
    parentPort!.postMessage(`${workerData.message}, world!`);
  }
}

run();

실행

워커 스레드를 실행하는 코드를 bootstrap 함수에 정의하였습니다. 스레드를 생성하고, 메세지를 받아오는 지 확인하기 위해 아래와 같이 작성하고 실행합니다.

// index.ts

// ... (생략)

async function run() {
  const message = await bootstrap();
  console.log(message);
}

run().catch((err) => console.error(err));

참조

Worker threads

profile
Dart와 TypeScript를 다룹니다.

0개의 댓글