NestJS 독학 - Module

김정원·2020년 11월 15일
1

NestJS 독학

목록 보기
4/4
post-custom-banner

Module

모듈은 @Module 데코레이터로 정의된 클래스이며, 이 모듈들의 조합을 통해 NestJS의 구조가 결정된다.

애플리케이션은 반드시 하나의 Root Module이 있어야 작동하며 그 외의 기능들을 구현하는 모듈들을 Root Module로 연결하여 사용한다. @Module 데코레이터는 아래의 인자들을 받아 모듈을 구성할 수 있다.

  • providers: Injectable된 클래스들을 인스턴스화 하고 인스턴스는 모듈 안에서 최소한으로 공유된다.
  • controllers: 해당 모듈에서 사용되는 컨트롤러의 모음을 인스턴스화 해준다.
  • imports: 다른 모듈들을 임포트하여 연결해준다. export된 provider가 있다면 사용할 수 있다.
  • exprots: 임포트하는 모듈에서 사용할 provider를 지정할 수 있다.

Feature module

앞서 만든 CatsController와 CatsService는 같은 영역에서 서로 연결할 수 있기 때문에 하나의 Feature Module로 묶을 수 있다. 하나의 module내의 providercontroller는 모듈 내에서만 사용하는 것이 원칙이다. 이렇게 해야 코드가 조직적으로 운영되어 SOILD원칙을 준수할 수 있다.

아래 예제를 통해 cats.module.ts 모듈을 정의해 보자.

// cats/cats.module.ts

import {Module} from "@nestjs/common";
import {CatsController} from "./cats.controller";
import {CatsService} from "./cats.service";

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

controllerprovider@Module 데코레이터를 통해 CatsModule 클래스를 정의하고 export 해준다. CatsModule은 이제 다른 모듈에 import시킬 수 있다. 만약 import될 모듈에서도 CatsService provider를 사용하고 싶다면 CatsService provider를 export 해줄 수 있다.

이제 root module인 AppModule에서 import 해보자.

// app.module.ts

import {Module} from "@nestjs/common";
import {CatsModule} from "./cats/cats.module";

@Module({
    imports: [CatsModule]
})
export class AppModule{}

Shared modules

앞서 말했듯이 모든 모듈은 싱글톤이기 때문에 다른 모든 모듈에서도 export하여 사용할 수 있다.

Dependency injection

모든 모듈은 의존성을 주입해 둘 수 있다. 단 모듈 클래스 자체를 provider로 주입하는 건 불가능하다.

라고 공식 문서에 나와있지만, 어떤 경우에 Module에 provider를 injection하는 건지는 모르겠다..

// cats.module.ts
import {Module} from "@nestjs/common";
import {CatsController} from "./cats.controller";
import {CatsService} from "./cats.service";

@Module({
    controllers: [CatsController],
    providers: [CatsService]
})
export class CatsModule {
    constructor(private catsService: CatsService) {}
		//constructor를 통해 CatsModule에 의존성을 주입한다.
}

Global modules

모듈에 @Global 데코레이터를 달면 모든 모듈에서 사용 가능한 글로벌모듈이 된다. 글로벌 모듈은 단 하나만 가능하며 글로벌모듈을 별도로 import없이 모든 모듈에서 provider를 사용할 수 있다. (물론 export는 해줘야 한다.)

Dynamic modules

NestJS의 모듈을 100% 활용하기 위한 강력한 기능이다. 이 방법을 통해 모듈을 import할 때 커스텀을 할 수 있는데 이를 통해 provider를 동적으로 설정하고 등록할 수 있게 해준다. 동적 모듈은 너무 방대한 내용이기 때문에 여기를 통해 자세히 알아보기로 하자.

아래는 동적 모듈을 만드는 예제이다.

import {Module, DynamicModule} from "@nestjs/common";
import {createDatabaseProviders} from "./database.providers";
import {Connection} from "./connection.provider";

@Module({
    providers: [Connection]
		//기본적으로 Connection provider를 포함하고 있는 모듈이다.
})
export class DatabaseModule {
    static forRoot(entities = [], options?): DynamicModule {
		//forRoot static 메소드를 통해 인수를 받아 동적으로 모듈을 정의한다.
        const providers = createDatabaseProviders(options, entities);
        return {
            module: DatabaseModule,
						//동적으로 재구성할 모듈을 지정한다.
            providers,
            exports: providers
        }
				//동적으로 모듈을 재구성한다.
    }
}

이렇게 정의된 동적 모듈을 아래와 같이 import하게 되면 인자에 맞춰 재구성된다

@Module({
    imports: [DatabaseModule.forRoot([User])]
})

이렇게 만들어진 조립하듯이 맞춰서 서버를 동작시키는 것이 NestJS의 기본적인 컨셉이다. 간단한 서버를 돌릴 때는 성능이나 설계에서 큰 장점이 없지만, 서버의 규모가 커지고 협업을 하게 될수록 NestJS의 장점이 커진다고 한다.


이 외에도 공식문서에는 Middlewere나 Guards등의 기능을 설명하고 있지만 일단 당장은 GraphQL을 동작하는 게 먼저이니 필요할 때 찾아보는 걸로 하고 NestJS에 대한 공부는 여기까지만 하기로 했다.

profile
영원히 공부중
post-custom-banner

2개의 댓글

comment-user-thumbnail
2020년 11월 15일

Nest 배우시는 분이 있다니 반갑네요 ㅎㅎㅎ

1개의 답글