docs.nestjs.com/modules#dynamic-modules
docs.nestjs.com/fundamentals/dynamic-modules#dynamic-modules
모듈은 근본적으로 DynamicModule과 StaticModule로 나뉘어진다. DynamicModule은 커스터마이징이 가능한 모듈을 만들수 있는 모듈이다. 쉽게 말해 옵션을 줘서 또 다른 모듈을 반환하는 동적인 모듈이다.
The Nest module system includes a powerful feature called dynamic modules. This feature enables you to easily create customizable modules that can register and configure providers dynamically.
단적으로, AppModule에 가서 아무 모듈이나 확인해보면, 옵션을 준 모듈은 DynamicModule으로 타이핑이 된 것을 볼 수 있다.
Dynamic Module 만들기
공식 문서를 하나씩 보며 따라해보자. 문서에서는 DatabaseModule 이라는 다이나믹 모듈을 만든다고 하네요.
우선 nest cli를 이용해 빈 모듈을 하나 만들어주자. 여기서는 jwt를
nest g mo [모듈이름]
import { Module } from '@nestjs/common';
@Module({})
export class JwtModule {}
* forRoot라는 statc 메서드는 반드시 forRoot라는 이름일 필요는 없지만 nest의 convention이기 때문에 따르는게 좋다.
* @Global을 통해 global 모듈을 만들 수 있다. 문서에 따르면 return하는 객체에 global을 넣어 글로벌 모듈을 만들 수도 있다. global module이 아니면 사용하고자 하는 scope에 imports해줘야 한다. 그러나 이런 불편함 때문에 모든 모듈을 global module로 만드는 것은 좋지 않다.
* 글로벌 모듈이면 사용하고자 하는 Module에 import할 필요 없이 그냥 가져다 쓰면 된다. user Module을 만들고 Service를 provide로 넣은 후에 user Module을 global로 만든다면 관련 Service를 다른 곳의 Service나 다른 곳에서 자유롭게 사용할 수 있다는 것이다.
글로벌 모듈은 : darrengwon.tistory.com/849 여기를 참고합시다.
@Module({})
@Global()
export class JwtModule {
static forRoot(): DynamicModule {
return {
global: true
module: JwtModule,
exports: [JwtService],
providers: [JwtService],
};
}
}
여튼, global? module, export, porivde 를 필요에 따라 구성한 후 return하면 우선 기본적인 Dynamic Module이 된 것이다.
이후, 추가적으로 옵션을 받아 forRoot에서 사용할 수 있도록 만들어주었다. 결론적으론 이거 하려고 dynamic module을 만드는 겁니다.
export interface JWTModuleOptions {
privateKey: string;
}
@Module({})
@Global()
export class JwtModule {
static forRoot(options: JWTModuleOptions): DynamicModule {
return {
...options,
global: true,
module: JwtModule,
providers: [
{
provide: CONFIG_OPTIONS,
useValue: options,
},
{
provide: JwtService,
useClass: JwtService,
},
],
exports: [JwtService],
};
}
provider injection
provider에 무언가를 주입하면 exports한 곳에서 해당 내용을 사용할 수 있다.
provider에 넣을 수 있는 타입을 체크해보니 다음과 같은 Provider들이 존재하는 것을 확인할 수 있었다.
export declare type Provider<T = any> = Type<any> | ClassProvider<T> | ValueProvider<T> | FactoryProvider<T> | ExistingProvider<T>;
ClassProvider => {provide, useClass, scope}
ValueProvider => {provide, useValue}
FactoryProvider => {provide, useFactory, inject, scope}
ExistingProvider => {provide, useExisting}
forRoot 메서드를 통해 Dynamic Module을 정의하여 사용하는 곳(AppModule)에서 options을 받아와 해당 option을 'banana'라는 이름으로 provide해주었습니다.
@Module({})
@Global()
export class JwtModule {
static forRoot(options: JWTModuleOptions): DynamicModule {
return {
...options,
global: true,
module: JwtModule,
providers: [
{
provide: 'Banana',
useValue: options,
},
{
provide: JwtService,
useClass: JwtService,
},
],
exports: [JwtService],
};
}
}
provider에서 받는 내용들은 @Inject를 통해 넣어줄 수 있다. provide 가 nest 설명으로는 injection token이라는데 쉽게 말해서 provide해준 내용을 Inject하기 위한 식별자이다. 위에선 Banana이니까 Banana로 inject한다.
import { Inject, Injectable } from '@nestjs/common';
import { JWTModuleOptions } from './interfaces/jwt-module-options.interface';
@Injectable()
export class JwtService {
constructor(@Inject('Banana') private readonly options: JWTModuleOptions) {
console.log(options);
}
hello() {
console.log('hello');
}
}
'Node, Nest, Deno > 🦁 Nest.js' 카테고리의 다른 글
Guard + MetaData (0) | 2020.11.24 |
---|---|
Nest Middleware (0) | 2020.11.24 |
dotenv 대신 @nestjs/config을 사용해야하는 이유 + 활용 (0) | 2020.11.21 |
DTO를 통한 검증을 위한 Pipe (Class Validator + mapped-types ...) (0) | 2020.11.19 |
Module에 대한 이해와 간단한 DI (0) | 2020.09.25 |