NestJS 프로젝트를 진행하면서 의존성 주입을 배열로 받아야 하는 경우가 있었다.
Spring 의 경우 배열로 선언하면 interface 를 구현한 구현체를 알아서 배열로 세팅해주지만 NestJS 에서는 예쁘게 지원이 안된다. 명시적으로 선언하는 방식으로 해야하는데 어떻게 하는지 알아보자.
아래와 같은 service 를 만든다.
@Injectable() export class AppService { constructor(@Inject('handlers') private readonly handlers: Handler[]) {} handleRequest(key: string): void { for (const handler of this.handlers) { if (handler.isResponsible(key)) { handler.handle(); } } } }
app.module 파일을 아래와 같이 설정해본다.
@Module({ controllers: [AppController], providers: [ AppService, { provide: 'handlers', useClass: FooHandler, }, { provide: 'handlers', useClass: BarHandler, }, ], }) export class AppModule {}
서버를 실행해 보면 실행이 된다.
그리고 service 에서 handlers 를 찍어보면
?? handlers 프로퍼티에 왠 BarHandler 하나만 들어와있다.
NestJS 의 의존성 컨테이너는 동일한 키로 여러번 등록하는 경우 그냥 덮어쓴다는걸 예상할 수 있다.
app module 을 아래와 같이 수정해보자
@Module({ controllers: [AppController], providers: [ AppService, FooHandler, BarHandler, { provide: 'handlers', useFactory: (foo, bar) => [foo, bar], inject: [FooHandler, BarHandler], }, ], }) export class AppModule {}
다시 service 에서 handlers 를 찍어보면
배열로 잘 들어온 것을 확인할 수 있다.
결국 배열에 새로운 객체를 추가로 주입하는 경우 use factory 함수를 변경해 줘야하고, provider 배열에 새로 구현된 구현체를 추가해줘야 한다.
Reference
배열로 의존성 주입을 지원하기 위한 core feature PR
기능으로 추가될 듯 하다가 결국 closed 처리 되었다.
구현 상 어려움이 있었고, 명시적인 방법으로 가능해서 그냥 close 처리한 듯 하다.