[Nestjs] Nestjs에서의 Worker Thread 사용

아홉번째태양·2023년 5월 9일
1

일반적인 worker thread 사용

Nestjs 프로젝트에서 nest 커맨드를 이용해 프로젝트를 시작할 경우 항상 컴파일이 이루어지기 때문에 ts-node만을 사용할 때처럼 타입스크립트 워커 파일을 읽기 위한 js파일이나 allowJS 옵션에 대해 신경쓸 필요가 없다.

따라서, 단순히 worker thread를 사용할 때는 빌드된 파일 경로를 사용하여 일반적인 Nodejs 프로젝트에서 사용하는 것과 같은 방법으로 사용이 가능하다.

  • app.service.ts
import { Injectable } from '@nestjs/common';
import * as path from 'path';
import { Worker } from 'worker_threads';

@Injectable()
export class AppService {
  getHello(): string {
    const workerData = {
      data: 'hello'
    }
    const worker = new Worker(
      // 어차피 빌드된 파일을 읽기 때문에 ts가 아닌 js 파일을 넣는다.
      path.join(__dirname, 'workers', 'node-worker.js'),
      { workerData }
    );

    worker.on('message', (result) => {
      console.log('worker result', result);
    });

    worker.on('exit', (code) => {
      console.log('worker exit', code);
    });

    return 'Hello World!';
  }
}
  • worker/node-worker.ts
import { parentPort, workerData } from 'worker_threads';

const { data } = workerData;
console.log('this is worker', data);
parentPort.postMessage(data + ' world!!');
  • 결과
this is worker hello
worker result hello world!!
worker exit 0

Worker에서 의존성 사용

하지만 위와 같은 worker thread 사용 방식은 Nestjs IoC 컨테이너에 등록된 다른 의존성 모듈들을 사용하지 못한다는 단점이 있다. 그래서 필요한 의존성들은 직접 worker에 다시한번 작성하는 수 밖에 없는데, Nestjs에서는 이런 경우 createApplicationContext를 이용해 standalone 애플리케이션을 생성함으로서 자유롭게 의존성을 주입할 수 있도록 해준다.

  • test.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class TestService {
  add(a: string) {
    return a + ' world??';
  }
}
  • worker/nest-worker.ts
import { NestFactory } from '@nestjs/core';
import { parentPort, workerData } from 'worker_threads';
import { AppModule } from 'src/app.module';
import { TestService } from 'src/test.service';

async function run() {
  const app = await NestFactory.createApplicationContext(AppModule);
  const testService = app.get(TestService);

  const { data } = workerData;
  console.log('this is nest worker', data);
  parentPort.postMessage(testService.add(data));
}

run();
  • 결과
[Nest] 10178  - 05/09/2023, 9:17:11 PM     LOG [NestFactory] Starting Nest application...
[Nest] 10178  - 05/09/2023, 9:17:11 PM     LOG [InstanceLoader] AppModule dependencies initialized +8ms
[Nest] 10178  - 05/09/2023, 9:17:11 PM     LOG [RoutesResolver] AppController {/}: +7ms
[Nest] 10178  - 05/09/2023, 9:17:11 PM     LOG [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 10178  - 05/09/2023, 9:17:11 PM     LOG [NestApplication] Nest application successfully started +1ms
[Nest] 10178  - 05/09/2023, 9:17:15 PM     LOG [NestFactory] Starting Nest application...
worker result(pid:10178) hello world??
[Nest] 10178  - 05/09/2023, 9:17:15 PM     LOG [InstanceLoader] AppModule dependencies initialized +5ms
this is nest worker(pid:10178) hello
worker exit 0

이처럼 worker가 실행되면서 새로운 애플리케이션이 실행되고 TestService라는 의존성도 정상적으로 주입되어 사용됨을 확인할 수 있다.

단, 주의해야할 점은 새로운 애플리케이션이 생성된다고해서 프로세스가 분리되는 것은 아니라는 점이다.




참고자료
nestjs-dependency-injection-in-worker

0개의 댓글