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 |
---|