Module
- 모듈은
@Module() 데코레이터가 붙은 클래스로 NestJS에서 모듈은 관련된 기능들을 하나의 단위로 묶는 역할을 한다.
- 관련된 기능들을 모듈 단위로 구성하면 다음과 같은 장점이 있다.
- 강력한 캡슐화 (Encapsulation)
- 모듈 내부의 컴포넌트는 기본적으로 해당 모듈 내에서만 사용할 수 있도록 격리 된다.
- 체계적인 구조
- 애플리케이션의 기능들을 명확한 단위로 나눌 수 있어 코드 구조를 이해하기 쉽고 유지보수하기 좋아진다.
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() 데코레이터의 주요 속성
providers
- 해당 모듈 내에서 사용될 프로바이더(서비스, 레포지토리, 팩토리)의 목록
controllers
- 이 모듈이 관리할 컨트롤러의 목록으로, HTTP 요청을 처리하고 응답을 반환하는 역할을 하는 클래스 리스트이다.
imports
- 다른 모듈을 가져올 때 사용하며,
imports 배열에 다른 모듈을 추가하면, 그 모듈이 내보낸(exports) 프로바이더들을 현재 모듈 내에서 사용할 수 있게 된다.
exports
- 현재 모듈의 프로바이더를 다른 모듈에 공유하고 싶을 때 사용한다.
exports에 추가하지 않으면, 해당 프로바이더는 이 모듈 내부에서만 사용할 수 잇게 비공개(private) 상태로 유지 된다.
기능 모듈 (Feature Modules)
- 애플리케이션이 커지면 모든 것을
AppModule에 넣는 대신, 특정 기능별로 모듈을 분리하는 것이 좋다. 기능별로 모듈을 만들고, AppModule에서 이 기능 모듈들을 imports하여 애플리케이션을 조립니다.
@Module({
imports: [CatsModule, DogsModule, HumanModule]
})
export class AppModule {}
공유 모듈 (Shared Modules)
- 여러 기능 모듈에서 공통적으로 사용되는 기능 (설정, 데이터 베이스 연결, 로깅 등)은 공유 모듈로 만들어 재사용할 수 있다.
- 공유 모듈을 만들기 위해서는 공통 프로바이더를
providers와 exports에 모듀 추가 한다. exports된 프로바이더는 이 공유 모듈을 imports하는 다른 모든 모듈에서 사용할 수 있게 된다.
@Module({
providers: [ConfigService],
exports: [ConfigService]
})
export class ConfigModule {}
전역 모듈 (Global Modules)
- 데이터 베이스 연결, 로깅, 설정 등 애플리케이션의 모든 곳에서 사용되어야 하는 프로바이더 같은 경우, 모듈에
@Global() 데코레이터를 붙여 전역 모듈로 생성한다.
- 전역 모듈은
AppModule에 imports하면, 해당 프로바이더 들을 다른 모든 모듈에서 imports 선언 없이 바로 주입 받아 사용할 수 있다.
@Global()
@Module({
providers: [DatabaseService],
exports: [DatabaseService]
})
export class DatabaseModule {}
@Global()을 사용하면 편리하지만, 의존성 관계가 불분명 해지는 등 프로젝트의 구조가 복잡해 질 수 있다.
동적 모듈 (Dynamic Modules)
- 사용자가 옵션을 전달하여 동작을 다르게 하고 싶을 때 동적 모듈을 사용한다.
- 동적 모듈은
forRoot()나 register()와 같은 정적 메서드를 통해 모듈을 동적으로 생성하고 반환하는 고급 패턴이다.
- 이 메서드는 옵션 객체를 받아 그에 맞는 프로바이더를 설정하여 반환할 수 있다.
TypeOrmModule.forRoot({...})