NestJS

[NestJS] custom-providers

NJ94 2023. 9. 11. 18:57

https://docs.nestjs.com/fundamentals/custom-providers

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea

docs.nestjs.com

 

😀 custom-providers

 

- Nest가 클래스를 인스턴스화(또는 캐시된 인스턴스 반환) 하는 대신 커스텀 인스턴스 생성하고싶을때

- 두 번째 종속성에서 기존 클래스를 재사용

- 테스트를 위해 모의버전으로 클래스를 재정의 

 


@ useValue()

1. 상수 주입

2. 외부 라이브러리 Nest 컨테이너에 주입

 - 외부 라이브러리를 import 로 가져와도 상관 없지만, 외부 라이브러리가 여러 service 에 필요하다고 했을 경우,

 useValue()로 외부라이브러리를 주입해서 여러 service에서 공통으로 공유가 가능하다

3. 실제 구현을 모의 개체로 바꾸는데 유용

 

1. 상수 주입

import { connection } from './connection';

@Module({
  providers: [
    {
      provide: 'CONNECTION',
      useValue: connection,
    },
  ],
})
export class AppModule {}
@Injectable()
export class CatsRepository {
  constructor(@Inject('CONNECTION') connection: Connection) {}
}

 

connection 이 예를들어서, db 연결하는 객체라면 

유용하게 공통적으로 사용이 가능해보인다.

 

아래는 DB 연결의 옵션 값이지만,  보통 저 옵션은 다른곳에서 관리하지만, ex) .env 
DB와 연결되어있는 객체를 따롭게 생성하고 

 

DB 연결하는 로직을 service 단에서 매번 DB연결 객체를 import 하는것보다

@inject를 통해서 공통적으로 가져왔을경우,  추후 유지보수에 매우 개발 비용과 시간을 줄일 수 있을듯 보인다.

 

const dbConfig = {
  host: 'localhost',
  port: '3000',
};

@Module({
  providers: [    
    {
      provide: "dbConnect",
      useValue: dbConfig,
    }
  ],
})

export class AppModule { }
import { Inject, Injectable } from "@nestjs/common";

@Injectable()
export class CustomProviderService {

    constructor(@Inject("dbConnect") private readonly dbConfig) {}

    findOne() {
        console.log('dbConfig: ', this.dbConfig);
        
        return "hello";
    }
}

 

 

2. 외부 라이브러리 Nest 컨테이너에 주입

$ npm install dateformat@3
// CommonJS 모듈 버전을 설치
import * as dateFormat from 'dateformat';

@Module({
  providers: [    
    {
      provide: "dateFormat",
      useValue: dateFormat,
    }
  ],
})

export class AppModule { }
import { Inject, Injectable } from "@nestjs/common";

@Injectable()
export class CustomProviderService {

    constructor (@Inject("dateFormat") private readonly dateFormat ) {}

    findOne() {        
        let now = new Date();
        console.log(this.dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT"));
        
        return "hello";
    }
}

 

3. 실제 구현을 모의 개체로 바꾸는데 유용

import { CatsService } from './cats.service';

const mockCatsService = {
  /* mock implementation
  ...
  */
};

@Module({
  imports: [CatsModule],
  providers: [
    {
      provide: CatsService,
      useValue: mockCatsService,
    },
  ],
})
export class AppModule {}

 

useValue 사용 시, CatsController에서 CatsService 내에 메서드를 호출 시, 

mockCatsService에 동일한 메서드가 호출된다.

 

여기서 중요한건, CatsService에 findOne 의 메서드가 명시되어있다면,

mockCatsService에도 동일한 메서드가 존재해야된다.

 


@useFactory