심심한 개발자의 취미생활

Module

  • 모듈은 @Module() 데코레이터가 붙은 클래스로 NestJS에서 모듈은 관련된 기능들을 하나의 단위로 묶는 역할을 한다.
  • 관련된 기능들을 모듈 단위로 구성하면 다음과 같은 장점이 있다.
    • 강력한 캡슐화 (Encapsulation)
      • 모듈 내부의 컴포넌트는 기본적으로 해당 모듈 내에서만 사용할 수 있도록 격리 된다.
    • 체계적인 구조
      • 애플리케이션의 기능들을 명확한 단위로 나눌 수 있어 코드 구조를 이해하기 쉽고 유지보수하기 좋아진다.
// cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
import { CatsService } from './cats.service'

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

@Module() 데코레이터의 주요 속성

  1. providers
    • 해당 모듈 내에서 사용될 프로바이더(서비스, 레포지토리, 팩토리)의 목록
  2. controllers
    • 이 모듈이 관리할 컨트롤러의 목록으로, HTTP 요청을 처리하고 응답을 반환하는 역할을 하는 클래스 리스트이다.
  3. imports
    • 다른 모듈을 가져올 때 사용하며, imports 배열에 다른 모듈을 추가하면, 그 모듈이 내보낸(exports) 프로바이더들을 현재 모듈 내에서 사용할 수 있게 된다.
  4. exports
    • 현재 모듈의 프로바이더를 다른 모듈에 공유하고 싶을 때 사용한다.
    • exports에 추가하지 않으면, 해당 프로바이더는 이 모듈 내부에서만 사용할 수 잇게 비공개(private) 상태로 유지 된다.

기능 모듈 (Feature Modules)

  • 애플리케이션이 커지면 모든 것을 AppModule에 넣는 대신, 특정 기능별로 모듈을 분리하는 것이 좋다. 기능별로 모듈을 만들고, AppModule에서 이 기능 모듈들을 imports하여 애플리케이션을 조립니다.
// app.module.ts
@Module({
    imports: [CatsModule, DogsModule, HumanModule]
})
export class AppModule {}

공유 모듈 (Shared Modules)

  • 여러 기능 모듈에서 공통적으로 사용되는 기능 (설정, 데이터 베이스 연결, 로깅 등)은 공유 모듈로 만들어 재사용할 수 있다.
  • 공유 모듈을 만들기 위해서는 공통 프로바이더를 providersexports에 모듀 추가 한다. exports된 프로바이더는 이 공유 모듈을 imports하는 다른 모든 모듈에서 사용할 수 있게 된다.
// config.module.ts
@Module({
    providers: [ConfigService],
    exports: [ConfigService]
})
export class ConfigModule {}

전역 모듈 (Global Modules)

  • 데이터 베이스 연결, 로깅, 설정 등 애플리케이션의 모든 곳에서 사용되어야 하는 프로바이더 같은 경우, 모듈에 @Global() 데코레이터를 붙여 전역 모듈로 생성한다.
  • 전역 모듈은 AppModuleimports하면, 해당 프로바이더 들을 다른 모든 모듈에서 imports 선언 없이 바로 주입 받아 사용할 수 있다.
// database.module.ts
@Global()
@Module({
    providers: [DatabaseService],
    exports: [DatabaseService]
})
export class DatabaseModule {}
  • @Global()을 사용하면 편리하지만, 의존성 관계가 불분명 해지는 등 프로젝트의 구조가 복잡해 질 수 있다.

동적 모듈 (Dynamic Modules)

  • 사용자가 옵션을 전달하여 동작을 다르게 하고 싶을 때 동적 모듈을 사용한다.
  • 동적 모듈은 forRoot()register()와 같은 정적 메서드를 통해 모듈을 동적으로 생성하고 반환하는 고급 패턴이다.
  • 이 메서드는 옵션 객체를 받아 그에 맞는 프로바이더를 설정하여 반환할 수 있다. TypeOrmModule.forRoot({...})