NestJS 모듈이란? 모듈은 NestJS 애플리케이션의 기본 구성 단위입니다. @Module() 데코레이터로 장식된 클래스로, 관련된 기능들을 하나로 묶어 조직화합니다.
모듈의 역할
애플리케이션을 논리적인 단위로 분리
코드의 재사용성과 유지보수성 향상
의존성 관리를 명확하게 정의
애플리케이션의 구조를 체계적으로 구성
기본 모듈 구조 @Module() 데코레이터 속성 @Module ({ imports : [], controllers : [], providers : [], exports : [] }) export class MyModule {}
루트 모듈 (Root Module) 모든 NestJS 애플리케이션은 최소한 하나의 루트 모듈을 가져야 합니다.
app.module.ts import { Module } from '@nestjs/common' ;import { AppController } from './app.controller' ;import { AppService } from './app.service' ;@Module ({ imports : [], controllers : [AppController ], providers : [AppService ], }) export class AppModule {}
기능 모듈 (Feature Module) 특정 기능과 관련된 코드를 그룹화하는 모듈입니다.
예제: Users 모듈 생성
users/users.module.ts import { Module } from '@nestjs/common' ;import { UsersController } from './users.controller' ;import { UsersService } from './users.service' ;@Module ({ controllers : [UsersController ], providers : [UsersService ], exports : [UsersService ], }) export class UsersModule {}
users/users.service.ts import { Injectable } from '@nestjs/common' ;@Injectable ()export class UsersService { private users = [ { id : 1 , name : 'John Doe' , email : 'john@example.com' }, { id : 2 , name : 'Jane Smith' , email : 'jane@example.com' }, ]; findAll ( ) { return this .users ; } findOne (id: number ) { return this .users .find (user => user.id === id); } create (user: { name: string ; email: string } ) { const newUser = { id : this .users .length + 1 , ...user, }; this .users .push (newUser); return newUser; } }
users/users.controller.ts import { Controller , Get , Post , Body , Param } from '@nestjs/common' ;import { UsersService } from './users.service' ;@Controller ('users' )export class UsersController { constructor (private readonly usersService: UsersService ) {} @Get () findAll ( ) { return this .usersService .findAll (); } @Get (':id' ) findOne (@Param ('id' ) id: string ) { return this .usersService .findOne (+id); } @Post () create (@Body () createUserDto: { name: string ; email: string } ) { return this .usersService .create (createUserDto); } }
모듈 가져오기 (Imports) 다른 모듈에서 제공하는 기능을 사용하려면 imports 배열에 추가합니다.
posts/posts.module.ts import { Module } from '@nestjs/common' ;import { PostsController } from './posts.controller' ;import { PostsService } from './posts.service' ;import { UsersModule } from '../users/users.module' ; @Module ({ imports : [UsersModule ], controllers : [PostsController ], providers : [PostsService ], }) export class PostsModule {}
posts/posts.service.ts import { Injectable } from '@nestjs/common' ;import { UsersService } from '../users/users.service' ;@Injectable ()export class PostsService { constructor (private readonly usersService: UsersService ) {} getUserPosts (userId: number ) { const user = this .usersService .findOne (userId); return { user, posts : [], }; } }
공유 모듈 (Shared Module) 여러 모듈에서 공통으로 사용하는 기능을 제공하는 모듈입니다.
shared/shared.module.ts import { Module , Global } from '@nestjs/common' ;import { LoggerService } from './logger.service' ;import { UtilsService } from './utils.service' ;@Global () @Module ({ providers : [LoggerService , UtilsService ], exports : [LoggerService , UtilsService ], }) export class SharedModule {}
@Global() 데코레이터
전역 모듈로 만들면 한 번만 import하면 모든 곳에서 사용 가능
루트 모듈이나 코어 모듈에서만 import
남용하지 않도록 주의 (필요한 경우에만 사용)
동적 모듈 (Dynamic Module) 런타임에 설정을 받아 동적으로 구성되는 모듈입니다.
config/config.module.ts import { Module , DynamicModule } from '@nestjs/common' ;import { ConfigService } from './config.service' ;@Module ({})export class ConfigModule { static register (options : { folder : string }): DynamicModule { return { module : ConfigModule , providers : [ { provide : 'CONFIG_OPTIONS' , useValue : options, }, ConfigService , ], exports : [ConfigService ], }; } }
동적 모듈 사용 import { Module } from '@nestjs/common' ;import { ConfigModule } from './config/config.module' ;@Module ({ imports : [ ConfigModule .register ({ folder : './config' }), ], }) export class AppModule {}
모듈 재내보내기 (Re-exporting) 가져온 모듈을 다시 내보낼 수 있습니다.
@Module ({ imports : [CommonModule ], exports : [CommonModule ], }) export class CoreModule {}
실전 예제: 완전한 모듈 구조 프로젝트 구조 src/ ├── app.module.ts ├── users/ │ ├── users.module.ts │ ├── users.controller.ts │ ├── users.service.ts │ └── dto/ │ ├── create-user.dto.ts │ └── update-user.dto.ts ├── posts/ │ ├── posts.module.ts │ ├── posts.controller.ts │ ├── posts.service.ts │ └── dto/ │ └── create-post.dto.ts ├── auth/ │ ├── auth.module.ts │ ├── auth.controller.ts │ └── auth.service.ts └── common/ ├── common.module.ts ├── logger.service.ts └── utils.service.ts
app.module.ts - 모든 모듈 통합 import { Module } from '@nestjs/common' ;import { UsersModule } from './users/users.module' ;import { PostsModule } from './posts/posts.module' ;import { AuthModule } from './auth/auth.module' ;import { CommonModule } from './common/common.module' ;@Module ({ imports : [ CommonModule , UsersModule , PostsModule , AuthModule , ], }) export class AppModule {}
모듈 설계 베스트 프랙티스 1. 단일 책임 원칙 각 모듈은 하나의 명확한 책임만 가져야 합니다.
UsersModule - 사용자 관리PostsModule - 게시글 관리AuthModule - 인증/인가AppModule - 모든 기능 포함
2. 느슨한 결합 모듈 간의 의존성을 최소화합니다.
@Module ({ providers : [ { provide : 'IUserRepository' , useClass : UserRepository , }, ], }) @Module ({ providers : [UserRepository ], })
3. 명확한 경계 모듈의 공개 API를 exports로 명확히 정의합니다.
@Module ({ providers : [UsersService , UserRepository ], exports : [UsersService ], }) export class UsersModule {}
모듈 생성 CLI 명령어 nest g module users nest g resource users nest g module modules/users nest g module users --no-spec
모듈 로딩 순서
imports에 선언된 모듈들이 먼저 로드
현재 모듈의 providers 등록
controllers 인스턴스화
exports로 선언된 providers를 다른 모듈에서 사용 가능하게 함
순환 참조 문제 해결 모듈 간 순환 참조가 발생할 경우:
forwardRef() 사용 import { Module , forwardRef } from '@nestjs/common' ;import { PostsModule } from '../posts/posts.module' ;@Module ({ imports : [forwardRef (() => PostsModule )], }) export class UsersModule {}
import { Module , forwardRef } from '@nestjs/common' ;import { UsersModule } from '../users/users.module' ;@Module ({ imports : [forwardRef (() => UsersModule )], }) export class PostsModule {}
정리
모듈은 NestJS의 핵심 구성 요소
@Module() 데코레이터로 정의
imports, controllers, providers, exports로 구성
기능별로 모듈을 분리하여 관리
공유 모듈과 동적 모듈을 활용하여 유연성 확보
순환 참조는 forwardRef()로 해결
다음 단계 모듈 구조를 이해했다면:
컨트롤러로 라우팅 처리하기
서비스에서 비즈니스 로직 구현하기
의존성 주입 패턴 이해하기