앱이 제공하고자 하는 핵심 기능, 즉 비즈니스 로직을 수행하는 역할을 한다.
- 프로바이더는 서비스, 저장소, 팩터리, 헬퍼등 여러가지 형태로 구현이 가능하다.
- 프로바이더는 @Injectable() 데코레이터를 활용하여 선언한다.
- 프로바이더의 핵심은 의존성으 주입 할 수 있다는 것이다.
- 즉 컨트롤러는 프로바이더에서 의존성을 주입받아 복잡한 작업은 프로바이더에게 위임 해야 한다.
// service
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
}
findAll(): Cat[] {
return this.cats;
}
}
@Module({
...
providers: [CatsService]
})
export class CatsModule {}
//controller
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
프로바이더는 @Injectable() 데코레이터를 활용하여 선언하고, 컨트롤러의 constructor를 활용하여 의존성을 주입 할 수 있다.
단, 의존성을 주입하기 위해서는 module에 등록이 되어있어야 한다.
why? 앱이 실행될 때 Nest에서 등록된 의존성을 주입해 주는데 module에 프로바이더가 등록 되어 있지 않으면 Nest가 의존성 괸계를 찾을 수 없다.
ref) IoC
- Nest 프레임워크가 만들어주는 인스턴스 또는 캐시된 인스턴스 대신 인스턴스를 직접 생성하고 싶은 경우.
- 여러 클래스가 의존관계에 있을 때 이미 존재하는 클래스를 재사용하고자 할 때
- 테스트를 위해 모의 버전으로 프로바이더를 재정의 하려는 경우
export interface ModuleMetadata {
/**
* Optional list of imported modules that export the providers which are
* required in this module.
*/
imports?: Array<Type<any> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
/**
* Optional list of controllers defined in this module which have to be
* instantiated.
*/
controllers?: Type<any>[];
/**
* Optional list of providers that will be instantiated by the Nest injector
* and that may be shared at least across this module.
*/
providers?: Provider[];
/**
* Optional list of the subset of providers that are provided by this module
* and should be available in other modules which import this module.
*/
exports?: Array<DynamicModule | Promise<DynamicModule> | string | symbol | Provider | ForwardReference | Abstract<any> | Function>;
}
프로바이더를 등록할 때 Provider의 Array를 받는다. 그러면 Provider의 코드를 보자.
export declare type Provider<T = any> = Type<any> | ClassProvider<T> | ValueProvider<T> | FactoryProvider<T> | ExistingProvider<T>;
export interface ClassProvider<T = any> {
provide: InjectionToken;
useClass: Type<T>;
scope?: Scope;
inject?: never;
durable?: boolean;
}
export interface ValueProvider<T = any> {
provide: InjectionToken;
useValue: T;
inject?: never;
}
export interface FactoryProvider<T = any> {
provide: InjectionToken;
useFactory: (...args: any[]) => T | Promise<T>;
inject?: Array<InjectionToken | OptionalFactoryDependency>;
scope?: Scope;
durable?: boolean;
}
export interface ExistingProvider<T = any> {
provide: InjectionToken;
useExisting: any;
}
ClassProvider, ValueProvider, FactoryProvider 등을 받는다.