Dapr(Distributed Application Runtime)는 분산 환경에서 탄력적이고 확장 가능한 마이크로서비스를 구축할 수 있도록 돕는 이벤트 기반 런타임입니다. Nest.js 프레임워크와 Dapr JS SDK를 결합하면 서비스 간 통신, 상태 관리, 바인딩 등 Dapr의 강력한 기능들을 Nest.js의 의존성 주입(DI) 시스템 내에서 효과적으로 활용할 수 있습니다.
프로젝트 구조 설계
먼저 모듈화된 설계를 위해 src 디렉토리 하위에 Dapr 전용 모듈을 구성합니다.
src/
dapr/
dapr.module.ts
dapr.service.ts
config/
app.config.ts
app.module.ts
main.ts
Dapr 모듈 및 서비스 구현
DaprService를 통해 Dapr 클라이언트 인스턴스를 관리하고, 이를 DaprModule에서 제공하도록 설정합니다.
Dapr 서비스 생성
환경 변수에서 Dapr 사이드카 호스트와 포트 정보를 읽어와 DaprClient를 초기화합니다.
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DaprClient } from '@dapr/dapr';
@Injectable()
export class DaprProvider {
public readonly client: DaprClient;
constructor(private readonly config: ConfigService) {
const host = this.config.get('dapr.host') || '127.0.0.1';
const port = this.config.get('dapr.port') || '3500';
this.client = new DaprClient({ daprHost: host, daprPort: port });
}
}
Dapr 모듈 등록
서비스를 제공하고 내보내는 모듈을 생성합니다.
import { Module, Global } from '@nestjs/common';
import { DaprProvider } from './dapr.service';
@Global()
@Module({
providers: [DaprProvider],
exports: [DaprProvider],
})
export class DaprModule {}
애플리케이션 활용
생성된 DaprModule을 루트 모듈에 추가하면, 이제 어디서든 Dapr 기능을 주입받아 사용할 수 있습니다. 아래는 컨트롤러에서 Dapr 바인딩을 통해 외부 시스템과 통신하는 예시입니다.
import { Controller, Post, Body } from '@nestjs/common';
import { DaprProvider } from '../dapr/dapr.service';
@Controller('tasks')
export class TaskController {
constructor(private readonly dapr: DaprProvider) {}
@Post()
async executeTask(@Body() data: any) {
await this.dapr.client.binding.send('output-component', 'create', data);
return { status: 'success' };
}
}
Dapr 사이드카와 함께 실행
애플리케이션을 구동할 때는 Dapr CLI의 run 명령어를 사용하여 사이드카 프로세스와 함께 실행합니다.
dapr run --app-id nest-service \
--app-port 3000 \
--dapr-http-port 3500 \
--components-path ./components \
npm run start