주기적으로 동일한 작업을 처리해야할 때 태스크 스케줄링을 통해 만들수 있다. Node.js에는 크론 기능을 하는 여러 라이브러리가 있고 Nestsms node-cron을 통합한 @nestjs/schedule 패키지를 제공한다.
$ npm i --save @nestjs/schedule @types/cron
태스크 스케줄링은 ScheduleModule을 사용한다. 이 모듈을 AppModule에서 바로 사용해도 되지만 별도 모듈인 BatchModule에 작성한다.
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { TaskService } from './task.service';
@Module({
imports: [ScheduleModule.forRoot()],
providers: [TaskService],
})
export class BatchModule {}
크론 잡 선언 방식은 @Cron 데커레이터를 선언한 메서드를 태스크로 구현하는 방식이다.
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
@Injectable()
export class TaskService {
private readonly logger = new Logger(TaskService.name);
@Cron('* * * * * *', { name: 'cronTask' })
handleCron() {
this.logger.log('Task Called!');
}
}
@Interval 데커레이터를 사용하여 인터벌로 스케줄링을 할 수 있다.
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
@Injectable()
export class TaskService {
private readonly logger = new Logger(TaskService.name);
@Cron('* * * * * *', { name: 'cronTask' })
handleCron() {
this.logger.log('Task Called!');
}
@Interval('intervalTask', 3000) // 앱 실행 후 3초 후에 처음 수행되며, 3초마다 반복
handleInterval() {
this.logger.log('Task Called!');
}
}
앱이 실행된 후 태스크를 단 한번만 수행한다. @Timeout 데커레이터를 사용한다.
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
@Injectable()
export class TaskService {
private readonly logger = new Logger(TaskService.name);
@Cron('* * * * * *', { name: 'cronTask' })
handleCron() {
this.logger.log('Task Called!');
}
@Interval('intervalTask', 3000) // 앱 실행 후 3초 후에 처음 수행되며, 3초마다 반복
handleInterval() {
this.logger.log('Task Called!');
}
@Timeout('timeoutTask', 5000)
handleTimeout() {
this.logger.log('Task called by timeout');
}
}
앱 구동 중 특정 조건을 만족했을 때 태스크를 등록하도록 해보자. 이를 위해서는 태스크를 등록/해제할 방법이 필요하다. 동적 태스크 스케줄링은 SchedulerRegistry에서 제공하는 API를 사용한다.
import { Injectable, Logger } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';
import { CronJob } from 'cron';
@Injectable()
export class TaskService {
private readonly logger = new Logger(TaskService.name);
constructor(private schedulerRegistry: SchedulerRegistry) {
this.addCronJob();
}
addCronJob() {
const name = 'cronSample';
const job = new CronJob('* * * * * *', () => {
this.logger.warn(`run! ${name}`);
});
this.schedulerRegistry.addCronJob(name, job);
this.logger.warn(`job ${name} added!!`);
}
}
이 상태에서는 아무런 동작을 하지 않는다. 등록된 크론 잡을 스케줄링으로 동작시키고 중지하는 기능을 가진 컨트롤러를 추가해보자.
import { Controller, Post } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';
@Controller('batches')
export class BatchController {
constructor(private scheduler: SchedulerRegistry) {}
@Post('/start')
start() {
const job = this.scheduler.getCronJob('cronSample');
job.start();
console.log('start!! ', job.lastDate());
}
@Post('/stop')
stop() {
const job = this.scheduler.getCronJob('cronSample');
job.stop();
console.log('stop!! ', job.lastDate());
}
}
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { TaskService } from './task.service';
import { BatchController } from './batch.controller';
@Module({
imports: [ScheduleModule.forRoot()],
providers: [TaskService],
controllers: [BatchController],
})
export class BatchModule {}
본 포스트는 한용재 저자의 NestJS로 배우는 백엔드 프로그래밍을 기반으로 스터디하며 정리한 내용들입니다.