Provider 살펴보기

정리 하기 앞서 Provider 의 역할은 Dependency 를 Nest Core가 Register 할 수 있도록 등록하는 곳이라 이해하면 쉬울 듯 하다. 이런 Dependency들을 등록하기 위해서는 @Injectable() 이라는 데코레이터로 선언하여 사용할 수 있으며 NestJS 에서 제공 되는 Provider 종류는 아래 와 같다.

  • ClassProvider
  • ValueProvider
  • FactoryProvider
  • ExistingProvider

 

provider 인터페이스 경로

NestJs \node_modules\@nestjs\common\interfaces\modules\provider.interface.d.ts

 

Class Provider

인터페이스 정의

export interface ClassProvider<T = any> {
    /**
     * Injection token
     */
    provide: InjectionToken;
    /**
     * 주입할 인스턴스의 클래스.
     */
    useClass: Type<T>;
    /**
     * 주입한 인스턴스의 생명 주기 default Singleton
     */
    scope?: Scope;
    /**
     * 현재 ClassProvider 에 다른 프로바이더를 주입 할 경우 (선택적)
     */
    inject?: never;
		...
}

1. 의존성 주입이 가능한 클래스 데코레이터 표기

@Injectbale() 데코레이터를 정의하여 ExampleClassService 는 의존성 주입이 가능한 클래스임을 명시한다.

// example-class.service.ts

@Injectbale()
export class ExampleClassService {
   public getProfile(){
     return {
         name: 'dongmin', 
         age: 34,
         phone:'010-8796-9394'
     };
  }
}

2. 의존하는 서비스를 정의 하기 위한 모듈 클래스 작성 후 데코레이터 표기 

@Module() 데코레이터를 정의 하여 해당 모듈에서 사용할 프로바이더( providers) 리스트를 정의 한다.

 

이해하기 쉽게 정리 하자면 @Module() 데코레이터에서 providers 배열에 등록된 서비스 프로바이더들은 키-값 쌍으로 매칭되어 Nest의 IoC (Inversion of Control) 컨테이너에서 관리 되며 각 프로바이더는 키(토큰)와 서비스 인스턴스로 매핑된다.

// example-class.module.ts

@Module({
  providers: [
      {
        provide: ExampleClassService,
        useClass: ExampleClassService 
       }
   ],
   controllers:[
    ExampleClassController 
   ]
})
export class ExampleClassModule {}

위 코드에서 ExampleClassService는 providers 배열에 등록되었으며, 이것은 IoC 컨테이너에서 "ExampleClassService"라는 토큰과 ExampleClassService 클래스의 인스턴스를 매칭하게 되며.

 

이 서비스를 해당 모듈 또는 다른 모듈에서 주입하거나 사용할 수 있게 된다.

Value Provider

인터페이스 정의

export interface ValueProvider<T = any> {
    /**
     * Injection token
     */
    provide: InjectionToken;
    /**
     * 공급자의 인스턴스 값.
     */
    useValue: T;
    /**
	 * 현재 ValueProvider 에 다른 프로바이더를 주입 할 경우 (선택적)
     */
    inject?: never;
}

Value Provider는 클래스 대신 값을 주입할 때 사용되며 아래는 useValue를 사용하여 상수 값을 주입 한다.

const profileValue = {
  name: 'dongmin',
  age: 34,
  phone: '010-8796-9394',
};

@Module({
  providers: [
    {
      provide: 'PROFILE_VALUE',
      useValue: profileValue, // 상수 값을 주입
    },
  ],
})
export class ExampleValueModule {}

 

Factory Provider

인터페이스 정의

export interface FactoryProvider<T = any> {
    /**
     * Injection token
     */
    provide: InjectionToken;
    /**
     * 주입할 공급자의 인스턴스를 반환하는 팩토리 함수.
     */
    useFactory: (...args: any[]) => T | Promise<T>;
    /**
     * 현재 FactoryProvider 에 다른 프로바이더를 주입 할 경우 (선택적)
     */
    inject?: Array<InjectionToken | OptionalFactoryDependency>;
	...
}

Factory Provider는 주입될 객체를 생성하기 위한 팩토리 함수를 사용하며. 아래는 useFactory를 사용하여 객체를 생성한다.

class ProfileService {
  getProfile() {
    return {
      name: 'dongmin',
      age: 34,
      phone: '010-8796-9394',
    };
  }
}

@Module({
  providers: [
    ProfileService,
    {
      provide: 'PROFILE_FACTORY',
      useFactory: (profileService: ProfileService) => profileService.getProfile(),
      inject: [ProfileService], // 의존성 주입
    },
  ],
})
export class ExampleFactoryModule {}

 

 

Existing Provider

인터페이스 정의

export interface ExistingProvider<T = any> {
    /**
     * Injection token
     */
    provide: InjectionToken;
    /**
     * 지정할 공급자.
     */
    useExisting: any;
}

Existing Provider는 이미 등록된 다른 프로바이더를 래핑하여 새로운 프로바이더를 생성합니다. 아래는 useExisting를 사용하여 기존 프로바이더를 래핑한다.

class LoggerService {
  log(message: string) {
    console.log(message);
  }
}

@Module({
  providers: [LoggerService],
})
export class ExampleModule {}

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

const ExampleLoggerProvider = {
  provide: 'EXAMPLE_LOGGER',
  useExisting: LoggerService, // LoggerService를 래핑
};

@Module({
  providers: [ExampleLoggerProvider],
})
export class ExampleLoggerModule {}

 

정리

프로바이더는 NestJS의 의존성 주입 시스템의 핵심 구성 요소이며, 프로바이더를 사용하여 NestJS 애플리케이션을 구성하고 의존성을 관리할 수 있습니다. 코드의 변경 없이도 다른 구현체로 전환하거나, 특정 조건에 따라 동적으로 다른 프로바이더를 사용하는 데 유용합니다.

  • Class Provider (클래스 프로바이더): 클래스를 주입할 때 사용하며, useClass 속성에 클래스 타입을 지정합니다. 해당 클래스의 인스턴스가 주입됩니다.
  • Value Provider (값 제공자): 클래스 대신 값 또는 상수를 주입할 때 사용합니다. useValue 속성에 값을 할당하고, provide 속성에 해당 값에 대한 고유한 토큰을 제공합니다.
  • Factory Provider (팩토리 제공자): 주입될 객체를 생성하기 위한 팩토리 함수를 사용합니다. useFactory 속성에 팩토리 함수를 정의하고, 이 함수가 반환하는 값을 주입합니다.
  • Existing Provider (기존 제공자): 이미 등록된 다른 프로바이더를 래핑하여 새로운 프로바이더를 생성합니다. useExisting 속성에 기존 프로바이더를 지정하여 래핑합니다.

'Typescript' 카테고리의 다른 글

[NestJs] - 요청 라이프 사이클  (0) 2022.09.30

+ Recent posts