[Nest.JS] Custom Providers

장현수·2023년 7월 19일
0

Nest.JS

목록 보기
8/9

Providers

공식문서 파트
https://docs.nestjs.com/fundamentals/custom-providers

providers는 의존성 주입을 통해 다른 클래스에 주입될 수 있는 클래스이다.

custom provider의 3가지 타입

  • Class Provider
  • Value Provider
  • Factory Provider

1. Class Providers

src/app.module의 providers 배열을 보자.
축약 표기법

providers: [AppService]

위 구문은 사실 축약형이고, 아래와 같이 명시적으로 작성할 수 있다.

명시적 표기법

providers: [
    {
      provide: AppService, // token
      useClass: AppService, // class
    },

provide

  • provider를 등록할 때 제공되는 토큰이고, 일종의 식별자로 사용된다.
  • 의존성 주입시 이 토큰을 기준으로 provider를 검색하게 된다.

useClass

  • 의존성을 제공하는 클래스를 지정
  • 여기 사용된 클래스의 인스턴스가 의존성으로 주입된다.

축약형은 이 토큰과 클래스가 동일한 이름으로 지정되는 일반적인 경우를 반영한 표기법인 것이다.
이제 이 class provider를 custom provider로 적용해보자.


custom provider를 사용하기 위해 먼저, 새로운 service를 생성한다.

그리고 useClass를 새로운 service로 변경한다.

src/app.module

@Module({

  ...
  
  providers: [
    {
      provide: AppService,
      useClass: AppJapanService,
    }
]

provide(token)은 기존 서비스 토큰이고,
의존성 주입은 새로 생성한 service 클래스로 지정했다.

이렇게 되면, 이미 AppService를 주입받고 있던 app.Controller가 의존성을 주입받는 클래스가 AppJapanService가 되는 것이다.

그러면, app.Controller에서는 AppJapanService의 메소드를 실행한다.


2. Value Providers

두 번째로 Value Providers가 있다.
앞서 class providers는 class를 의존성으로 주입했다면, value providers는 값을 의존성으로 주입하는 것이다.

useValue

  • 의존성 주입에 사용할 값을 직접 제공한다.

위의 코드에서 provider를 추가해보자.

src/app.module

@Module({

  ...
  
  providers: [
    {
      provide: AppService,
      useClass: AppJapanService,
    },
    {
      provide: 'APP_NAME',
      useValue: 'Nest Events Backend!'
    }
]

token으로 'APP_NAME', 그리고 useValue에 'Nest Events Backend!'를 값으로 줬다.

그리고 Service 클래스에 이 값을 주입한다.

src/app.japan.service

import { Inject, Injectable } from '@nestjs/common';

@Injectable()
export class AppJapanService {
  constructor(
    @Inject('APP_NAME')
    private readonly name: string
  ) {  }
  getHello(): string {
    return `こんにちは世界! from ${this.name}`;
  }
}
  • @Inject() 데코레이터를 작성한다.
  • 방금 작성한 module의 provider에게서 의존성을 주입받을 값을 name이라는 변수명의 프로퍼티로 준다.
  • @Inject() 데코레이터 안에 아까 module에서 추가한 provider의 token 값인 'APP_NAME'을 파라미터로 전달한다.
  • 메소드로 해당 값을 this.name으로 불러오도록 했다.

결과값은 다음과 같다.

こんにちは世界! from Nest Events Backend!

이로써 value provider로 custom한 provider의 값을 잘 주입받아온 것을 확인할 수 있다.


3. Factory Provider

Factory Providers는 의존성 주입에 사용할 객체를 생성하는 팩토리 함수를 지정한다.
특정 이름의 provider를 반환하거나 팩토리 함수 그 자체로 의존성 주입에 사용될 수 있다.

inject

  • useFactory와 함께 사용되는 옵션으로, useFactory에서 사용할 다른 providers를 지정할 수 있다.
  • inject에는 배열로 의존성으로 주입받을 provider의 토큰을 지정한다.

useFactory

  • 의존성 주입에 사용할 객체를 생성하는 팩토리 함수를 지정한다.
  1. 클래스를 생성한다.

src/app.dummy.ts

export class AppDummy {
  public dummy(): string {
    return 'dummy';
  },
}

dummy()라는 하나의 메소드를 가진 클래스를 작성한다.

src/app.module.ts

    {
      provide: 'MESSAGE',
      inject: [AppDummy],
      useFactory: (app) => `${app.dummy()} Factory!`,
    },
    AppDummy,
  ]
  • 'MESSAGE'라는 토큰에 대한 provider를 등록한다.
  • inject 속성에 방금 생성한 클래스를 작성함으로써 해당 클래스(provider)를 의존성 주입받는다.
  • 따라서 useFactory 함수 내에서 AppDummy의 메소드를 사용할 수 있게 된다.
  • 팩토리 함수는 의존성을 주입받는 클래스를 인자로 받는다. (app)
  • useFactory에 지정한 팩토리 함수의 return 값을 'MESSAGE' 토큰이 받게 된다.

이제 Service 클래스에 'MESSAGE'를 주입받아 실행시켜서, dummy Factory! 값이 잘 출력될지 적용해보자.

src/app.japan.service.ts

import { Inject, Injectable } from '@nestjs/common';

@Injectable()
export class AppJapanService {
  // 의존성 주입
  constructor(
    @Inject('APP_NAME')
    private readonly name: string,
    @Inject('MESSAGE')
    private readonly message: string,
  ) {}
  getHello(): string {
    return `こんにちは世界! from ${this.name}, ${this.message}`;
  }
}

결과값은 다음과 같다.

こんにちは世界! from Nest Events Backend!, dummy Factory!
profile
개같이 발전하자 개발

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

이 글은 제게 많은 도움이 되었습니다.

답글 달기