Nest.js Bull

`Nest.js`는 강력한 백엔드 프레임워크로서, 복잡한 비즈니스 로직과 백그라운드 작업을 효과적으로 관리해야 할 때 사용할 수 있는 다양한 도구와 라이브러리를 제공합니다. 이 중에서도 `Bull.js`는 백그라운드 작업을 처리하기 위한 강력한 큐 라이브러리 중 하나로, `Nest.js`와 함께 사용하면 효율적인 작업 관리가 가능해집니다.


Bull.js란?

`Bull.js`는 `Node.js` 기반의 큐 라이브러리로, 백그라운드 작업을 비동기적으로 처리할 때 사용됩니다. `Bull.js`는 안정성과 성능을 중시하며, 다양한 기능과 옵션을 제공하여 다양한 상황에 적용할 수 있습니다.

 

 

Task

`Bull.js`에서 `task`는 큐(Queue)에 추가된 개별 작업을 나타냅니다. 이 작업은 비동기적으로 백그라운드에서 실행되어야 하는 일련의 작업 중 하나를 의미합니다. 예를 들어, 이메일 전송, 이미지 처리, 데이터 처리, 백엔드 작업 등 여러 종류의 작업이 큐에 추가될 수 있습니다.

 

작업(task)은 큐를 통해 비동기적으로 처리되기 때문에 큰 작업 부하를 주지 않고 여러 작업을 동시에 처리할 수 있으며, 실패한 작업을 재시도하거나 작업 상태를 모니터링하는 등의 기능을 제공합니다.

 

생명주기

`Bull.js`에서 작업(Task)의 생명주기는 작업이 큐에 추가되어 처리될 때까지의 과정을 설명합니다. 일반적으로 크게 4개의 stage로 나뉘며 자세하게는 다음과 같이 나뉩니다. 

 

 

작업 생성(Enqueue): 작업이 큐에 추가됩니다. 이 때 작업은 '대기(Waiting)' 상태로 들어갑니다. 대기 중인 작업은 실행을 위해 선택될 때까지 큐에 남아있습니다.

 

작업 선택(Active): 큐에서 작업 처리기(Worker)가 작업을 선택하면, 작업은 '활성(Active)' 상태가 됩니다. 이는 작업이 현재 처리 중임을 나타냅니다.

 

작업 완료(Completed): 작업이 성공적으로 완료되면, '완료(Completed)' 상태가 됩니다. 완료된 작업은 일반적으로 결과를 반환하고, 결과는 필요에 따라 저장하거나 다른 작업에 사용할 수 있습니다.

 

작업 실패(Failed): 작업 처리 중 오류가 발생하면, 작업은 '실패(Failed)' 상태가 됩니다. 실패한 작업은 일반적으로 로깅, 재시도, 오류 처리 등의 목적으로 사용됩니다.

 

작업 지연(Delayed): 작업은 설정된 시간만큼 지연되어 나중에 실행될 수 있습니다. 지연된 작업은 지정된 시간이 지나면 대기 상태로 돌아가 처리를 기다립니다.

 

작업 재시도(Retry): 실패한 작업은 설정에 따라 자동으로 재시도될 수 있습니다. 재시도 메커니즘을 사용하여 일시적인 오류나 네트워크 문제 등을 극복할 수 있습니다.

 

작업 제거(Remove): 작업이 완료되거나 특정 조건을 충족하면 큐에서 제거될 수 있습니다. 이는 시스템의 리소스를 관리하고, 큐를 깔끔하게 유지하는 데 도움이 됩니다.

 

작업 유지(Keep): 특정 설정에 따라, 작업이 완료된 후에도 큐에 남아있을 수 있습니다. 이는 추후 검토나 로깅 목적으로 사용될 수 있습니다.

 

상태 변화

각각의 Task의 상태를 변환하는 방법은 다음과 같은 조건을 따릅니다. 현재 태스크들의 상태와 수를 보고자 하면은 다음과 같은 함수를 작성하면 됩니다. 

const jobs = await this.testQueue.getJobCounts();

 

Waiting -> Active

`Waiting` 상태에 있는 데이터를 꺼내면은 자동으로 `Active`로 변경 됩니다.

const job = await this.testQueue.getNextJob();

 

Active -> Completed

`Completed` 하는 방법은 메소드를 통해 처리 가능합니다. 각각의 파라미터는 옵션을 나타내고 있습니다. 

await job.moveToCompleted("It's done!", true, true);

// moveToCompleted 설명
moveToCompleted(
  returnValue?: string, // 성공하면 반환 되는 값.
  ignoreLock?: boolean, // Queue Lock을 무시하고 성공으로 할지 여부
  notFetch?: boolean // 다음 Job을 자동으로 꺼낼지 여부 true시 수동으로 변경
): Promise<[any, JobId] | null>;

 

Active -> Failed

`Failed`로 메소드를 통해 처리 가능합니다. 

await job.moveToFailed({ message: error.message });

 

Consumer

`Consumer`는 `Queue`에 입력되 `Job`을 소비하는 클래스로 아래 사진과 같은 모양으로 데이터를 처리하고 있습니다. 데이터를 처리하는 방식도 간단하게 작성 할 수 있습니다. `getNextJob()` 함수를 사용하면 제일 먼저 처리 되어져야 하는 `job`이 나오고 처리를 하면 됩니다. 

await this.testQueue.add('test-job-1', { data });
await this.testQueue.add('test-job-2', { data });

 

 

각 `Job`은 `name`을 지정할 수 있는데 `name`에 맞게 `Process` 지정하여 자동으로 처리하도록 할 수 있습니다.

const job = await this.testQueue.getNextJob();

 

 

 

 

Processor

`Processor`는 `Bull.js`에서 작업을 처리하는 클래스 데코레이터입니다. 작업 처리를 담당하는 클래스에 `@Processor(queueName)` 데코레이터를 사용하여 해당 클래스가 어떤 큐에서 작업을 처리할지를 정의합니다.

import { Processor } from 'bullmq';

@Processor('myQueue')
class MyQueueProcessor {
  // 작업 처리 로직 구현
}

 

Process

`Process` 데코레이터는 `Processor` 클래스 내에서 실제 작업을 처리하는 메서드에 적용됩니다. 이 데코레이터는 해당 메서드가 어떤 작업을 처리해야 하는지를 정의합니다.

import { Process } from 'bullmq';

@Processor('myQueue')
class MyQueueProcessor {
  @Process('name')
  async handleJob(job: Job) {
    // 작업을 처리하는 로직을 여기에 구현
  }
}

 

 

 

주의사항

  • `add`시에  `jobId`를  지정이 가능한데 이때 `queue` 에서 제공하는 `id` 를 사용하지 않을 경우, `getNextJob()` 함수를 사용 불가 합니다. 
  • `completed` 와 `failed` 상태로 변경하고자 하면 제공되는 함수를 통해 가능합니다. 

 

 

 

 

 

'Backend > Nest.js' 카테고리의 다른 글

SSE(Server-Sent Event)  (0) 2024.02.02
Nest.js Integration Test 와 Mocking  (1) 2023.10.10
Nest.js mongodb-memory-server, cache 적용  (1) 2023.10.05
Nest.js Rate Limiting 설정  (0) 2023.09.30
Nest.js Swagger 보안 설정  (0) 2023.09.30