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

 

 

Request Lifecycle

Nest 애플리케이션은 요청 수명 주기 라고 하는 순서대로 요청을 처리하고 응답을 생성한다.

일반적으로 요청은 미들웨어를 통해 가드, 인터셉터, 파이프, 반환 경로의 인터셉터 순으로 흐른다.


미들웨어

  • 전역적으로 바인딩된 미들웨어를 먼저 실행
  • 이후 모듈 바인딩된 미들웨어를 실행
  • 서로 다른 모듈에 걸쳐 바인딩된 미들웨어는 루트 모듈에 바인딩된 미들웨어 실행, imports 배열에 모듈이 추가된 순서대로 미들웨어를 실행

가드

  • 글로벌 가드, 컨트롤러 가드, 라우트 가드 순으로 실행

인터셉터

  • 요청은 전역, 컨트롤러, 라우트 순으로 확인
  • 응답은 라우트, 컨트롤러, 전역 순으로 확인

파이프

  • 전역 파이프, 나중에 바인딩 되는 파이프 순으로 실행
  • 매개변수 별 파이프가 있는 경우 마지막 매개변수에서 첫번째 매개 변수로 실행

필터

  • 라우터, 컨트롤러, 전역 순으로 동작

일반적인 요청 수명 주기 순서

요청 

1. 미들웨어

2. 가드

3. 인터셉터(컨트롤러 실행 이전

4.파이프

5.컨트롤러

5-1.서비스

6. 인터셉터(컨트롤러 실행 이후)

7.예외필터

응답

'Typescript' 카테고리의 다른 글

[NestJs] - Provider 살펴보기  (1) 2023.10.26

+ Recent posts