Article#2 : NestJS - Module

roach·2021년 5월 30일
0

Article

목록 보기
2/3

NestJS - Module

  • 우리가 Module 클래스를 나타내기 위해서는 Class 단에 @Module() 데코레이터를 붙여줘야 한다. Module 데코레이터는 우리가 어플리케이션 구조에서 관계를 구축할 수 있게 해주는 것 같다.

  • 위의 사진은 NestJS 공식 Docs 에 나와있는 사진이다.

At least..

  • Nest Application 은 반드시 하나이상의 모듈을 가진다. 즉, Root Module 이 존재한다는 뜻! 이전 아티클을 읽었다면, Nest 가 어느정도의 어플리케이션 구조를 알고 있다는 것을 알것이다. 즉, Nest 는 Root Module 을 Entry Point 로 잡고 어플리케이션 그래프를 구축해 나간다.
  • Nest 는 가장 간단한 컴포넌트라도, Module 을 구축해 나가면서 진행해 나가길 권장한다. 각 개발 시간에 맞춰 진행하는 것이지만, 가능하다면 권장하는 편이다. 사실 이게 Module 의 근본적인 의미와도 가깝기 때문이지 않을 까 싶다.

Property

  • 많은 사람들이 모듈을 사용하면서 가장 헷갈려 하는 부분이 아래의 부분을 제대로 정리하지 않아서 일까 싶다.
  • 모듈은 4가지의 Property 를 가질 수 있다.
    • providers : 프로바이더는 간단히 얘기하면 해당 모듈에서 이 클래스 혹은 value 등등 (Article 1에서 설명함) 을 Nest 안에 집어 넣고 관리하겠다는 것이다. 즉 다른 A Module 이 B Module 을 Import 해가면 A Module 안에서 B Module 이 provider 에 넣어놨던 것들을 Dependency Injection 을 통해 주입받을 수 있게 된다. 스프링 보다 조금 더 세분화 했다고 생각하는 것이 좋다. (하지만 이런점때문에 순환 참조 문제가 생길 수도 있는데, 이는 나중에 설명하겠다.)
    • controllers : 해당 모듈에서 사용할 Controller 를 정의해 놓은 것이다.
    • imports : 어떤 모듈을 import 해올지 정하는 것
    • exports : provider 의 부분집합이다. 간단히 설명하면, 이 모듈에서 다른 모듈에서 사용할 수 있는 provider 를 등록해주는것이라고 생각하면 쉽다.

SingleTon

  • Nest 는 기본적으로 모듈을 SingleTon 으로 관리한다. 이 부분은 IoC Container 들이 보통 내부 Instance 를 어떻게 관리하면 좋을지를 생각해보면 , Map 자료구조를 이용할텐데, 그러다보면 자연스럽게 SingleTon 처럼 구성할 수 있게 되는 것이다. O(1) 의 복잡도와 싱글톤 구조까지 챙길 수 있는 것이다.

Module re-exproting

@Module({
  imports: [CommonModule],
  exports: [CommonModule],
})
export class CoreModule {}
  • 음 위처럼 CoreModule 이 CommonModule 을 Import 해온 뒤, CommonModule 을 재 exports 하는 형태를 지니고 있다. 어플리케이션 크기가 복잡해지다 보면 충분히 나올 수 있다고 본다.

Global Modules

  • 만약 우리의 어플리케이션에서 특정 모듈이 거의 전부 의존성을 지닌다고 했을때, 우리는 그것을 Global Scope 에 넣을 필요가 있다고 생각할 겁니다. 그래서 NestJS 에서는 모듈을 Global Scope 에 넣는 옵션을 제공합니다. 사용방법은 매우 간단하게 @Global() 데코레이터만 있으면 됩니다.
import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Global()
@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService],
})
export class CatsModule {}

Dynamic Modules

  • 이건 내가 진짜 좋아하는 방법중의 하나인데, Configure 를 동적으로 할 수 있어 상당히 재밌는 옵션이라고 생각한다. 뭐 라이브러리를 만든다는 느낌이 강해서 상당히 좋다고 생각한다.
  • 아래 코드를 한번 다같이 살펴보자
@Module({})
@Global()
export class JwtModule {
  static forRoot(options: JwtModuleOptions): DynamicModule {
    return {
      module: JwtModule,
      imports: [UsersModule],
      providers: [
        {
          provide: CONFIG_OPTIONS,
          useValue: options,
        },
        JwtService,
      ],
      exports: [JwtService, CONFIG_OPTIONS],
    };
  }
}
  • 위의 코드는 JwtModule 인데 forRoot 라는 것들통해 options 에 대한 속성을 받기를 원하고 있다. options 는 JwtModuleOptions 인데 JwtModuleOptions Type 은 아래와 같다.
export interface JwtModuleOptions {
  privateKey: string;
  tokenHeader: string;
}
  • privateKey 와 tokenHeader 를 Option 으로 받는다.
  • 따라서 JwtModule 을 Import 한 곳에서는 이러한 형태의값들을 지급해야지 해당 Module 을 정상적으로 이용가능하다. 아래는 AppModule 에서 JwtModule 을 Import 한 예시이다.
JwtModule.forRoot({
      privateKey: process.env.TOKEN_SECRET,
      tokenHeader: process.env.TOKEN_HEADER,
    }),
profile
모든 기술에는 고민을

0개의 댓글