NestJs Provider (With 역할과 구현)

이우길·2022년 3월 31일
0

NestJs

목록 보기
4/20
post-thumbnail

NestJs의 Custom Provider란? (With 역할과 구현)

예제코드는 github에 있습니다!

Goal

  • Custom Provider가 왜 나오게 되었는지에 대한 이해

  • Custom Provider의 사용법


Custom Provider가 왜 필요한가?

이전 글에서 작성한 것처럼 NestJsSpring과 달리 Interface타입으로 Provider를 등록할 수 없다.

찾아보니 이미 누가 issue를 등록하여 물어보았고 해당 issue는 아래와 같은 답변과 함께 닫혀있었다.


정리하자면 Typescript를 이용하여 정의한 Interface컴파일이 되면 사라지기 때문에 Interface타입으로는 DI를 받을 수 없다고 한다.


그럼 NestJs 역할과 구현으로 나눌 수 없는건가..?

결론부터 말하자면 나눌 수 있다.(Spring처럼 Interface를 구현하고 @Bean@Component를 추가하는 것보다는 조금 번거로울 수는 있다.)

먼저 InterfaceProvider로 등록했을 경우 어떻게 되는지 보자면 아래와 같다.

//ant-service.interface.ts
export interface AntService {
    work(): void
}

//ant.service.ts
@Injectable()
export class AntServiceImpl implements AntService{
  work(): void {
    console.log('working hardly');
  }
}

//ant.moduel.ts
@Module({
  controllers: [AntController],
  providers: [
    AntService
  ]
})
export class AntModule {}

위와 같이 code를 작성하면 compile error를 만날수 있다..!


Custom Provider를 이용하여 역할과 구현 분리하기

NestJs는 여러 Custom Provider를 제공하는데 그 중 ClassProvider를 이용하여 분리해보겠다. NestJs에서 제공하는 ClassProvider Interface는 다음과 같다.

export interface ClassProvider<T = any> {
    // export declare type InjectionToken = string | symbol | Type<any> | Abstract<any> | Function;
    provide: InjectionToken;
    useClass: Type<T>;
    scope?: Scope;
}

위의 Interface를 따라 CustomProvider를 만들어 Module에 등록할 수 있다. 위의 AntService를 이용해 예제코드로 작성하겠다.

const antService: ClassProvider = {
  provide: 'antService',
  useClass: AntServiceImpl
} 

@Module({
  controllers: [AntController],
  providers: [
    antService
  ]
})
export class AntModule {}

이와 같이 ClassProvider를 이용하여 CustomProvider를 만들어 Module에 등록을 해주었다. 그럼 해당 Provider를 가져다 쓰는 곳에서는 아래와 같이 역할(Interface) 타입으로 Provider를 주입받으면 된다.

@Controller('ant')
export class AntController {
  // 이전과 달리 구현class를 의존하는 것이 아닌 interface를 의존할 수 있게 되었다.
  constructor(@Inject('antService') private readonly antService: AntService){}

  @Get()
  excuteWork(){
      this.antService.work();
  }
}

Custom Provider를 이용하기 전까지는 AntControllerAntServiceImpl을 직접 주입받아 사용하였을 것이다. Custom Provider를 이용함으로 의존성을 낮추고 이 후 AntService의 구현체가 변경되더라도 AntModule에서만 변경해주면 된다.


정리

Custom Provider를 이용하여 Nest에서는 역할구현을 어떻게 나눠야 되는지 살펴보았다. (Custom Provider의 사용법이나 자세한 것들은 Custom Provider에서 살펴볼 수 있다.)

역할구현으로 나눔으로 코드 구조가 유연해졌으며, 이 후 확장이 가능해진다. 또한 Client Code를 수정하는 일이 줄어들 것이다.

Test Code를 작성할 때 Interface에 의존을 하다보니 구현 객체를 Mocking하여 넣어서 Test가 가능해진다. (테스트에 관련된 글을 작성할 때 CustomProvider를 이용한 유닛테스트를 진행해보겠다.)


Reference

profile
leewoooo

2개의 댓글

comment-user-thumbnail
2022년 6월 16일

좋은 글 잘보았습니다!
그런데 내용 중 궁금한게 하나 있는데
테스트 관련해서 interface에 의존하지 않더라도
Jest.mock을 이용하면 mocking할 수 있는데
Jest.mock으로 mock하는 것 과
구현 객체로 mock하는 것에 큰 차이가 있을까요?

1개의 답글