코딩일상

[Nest.js] @Module 알다가도 헷갈리는 모듈의 개념 정리!! 본문

개발 공부/nest.js

[Nest.js] @Module 알다가도 헷갈리는 모듈의 개념 정리!!

solutionMan 2026. 1. 12. 21:28
반응형

 

NestJS @Module 완벽 가이드

NestJS에서 가장 헷갈리기 쉬운 @Module 데코레이터를 쉽게 이해해봅시다!



목차

  1. @Module이란?
  2. ES6 import vs @Module imports
  3. @Module 속성 비교
  4. 회사 비유로 완벽 이해
  5. 실전 예제
  6. 자주 하는 실수

@Module이란?

@Module은 NestJS 애플리케이션을 구조화하는 핵심 단위입니다.

관련된 기능들(컨트롤러, 서비스 등)을 하나의 모듈로 묶어서 관리합니다.

@Module({
  imports: [],      // 다른 모듈 가져오기
  controllers: [],  // HTTP 요청 처리
  providers: [],    // 서비스/로직 등록
  exports: [],      // 외부에 공개
})
export class CoffeesModule {}

 


ES6 import vs @Module imports

가장 많이 헷갈리는 부분!

파일 상단의 import@Moduleimports완전히 다른 개념입니다.

1️⃣ ES6 import (JavaScript/TypeScript 문법)

import { Module } from "@nestjs/common";
import { CoffeesService } from "./coffees.service";
특징 설명
목적 코드 파일을 불러옴
시점 컴파일 시점
비유 📄 서류/문서를 복사해오기

2️⃣ @Module({ imports: [...] }) (NestJS 기능)

@Module({
  imports: [CoffeesModule, TypeOrmModule],
})
특징 설명
목적 다른 NestJS 모듈의 기능을 연결
시점 런타임 (앱 실행 시)
비유 🤝 부서 간 협업 계약

📊 비교 표

구분 ES6 import @Module({ imports })
위치 파일 최상단 @Module 데코레이터 안
대상 클래스, 함수, 변수 등 NestJS 모듈
역할 코드 참조 의존성 주입 연결
없으면? 컴파일 에러 DI 에러 (런타임)

@Module 속성 비교

부제:4가지 핵심 속성

@Module({
  imports: [],      // 🤝 다른 모듈의 기능 가져오기
  controllers: [],  // 🚪 HTTP 요청 처리 창구
  providers: [],    // 👨‍💼 서비스/로직 등록 (내부용)
  exports: [],      // 📤 외부에 공개할 것들
})

상세 비교표

속성 넣는 것 목적 비유
imports 모듈 외부 모듈 기능 사용 🤝 타 부서와 협업 계약
providers 서비스/클래스 내부에서 사용할 것 등록 👨‍💼 우리 부서 직원 채용
controllers 컨트롤러 HTTP 요청 처리 🚪 고객 응대 창구
exports 서비스/모듈 외부에 공개 📤 다른 부서에 빌려주기

 imports vs providers 핵심 차이

imports    = "남의 것" 빌려 쓰기 (모듈 단위)
providers  = "내 것" 만들어 쓰기 (서비스 단위)

 

회사 비유로 완벽 이해

NestJS 애플리케이션을 회사(Company) 로 비유해봅시다.

🏢 구조

AppModule (본사)
├── CoffeesModule (커피 부서)
├── UsersModule (고객관리 부서)  
└── OrdersModule (주문 부서)

📝 CoffeesModule 예시

@Module({
  // 🤝 imports: 협업할 다른 부서
  // "IT부서(TypeOrmModule)의 DB 기능을 빌려쓰겠습니다"
  imports: [TypeOrmModule.forFeature([Coffee])],

  // 🚪 controllers: 손님 응대 창구  
  // "커피 관련 요청은 여기서 받습니다"
  controllers: [CoffeesController],

  // 👨‍💼 providers: 우리 부서 직원들
  // "바리스타(CoffeesService)를 채용했습니다"
  providers: [CoffeesService],

  // 📤 exports: 타 부서에 빌려줄 것
  // "다른 부서도 우리 바리스타를 쓸 수 있게 해드릴게요"
  exports: [CoffeesService],
})
export class CoffeesModule {}

🔄 의존성 흐름도

┌─────────────────────────────────────────────────────────────┐
│  CoffeesModule (커피 부서)                                   │
│                                                             │
│  imports: [TypeOrmModule] ────────────────────────┐         │
│           ↓                                        │         │
│  "IT부서에서 Repository 기능 빌려왔어요"             │         │
│                                                    ▼         │
│  providers: [CoffeesService] ◄──── Repository 사용해서      │
│           ↓                         커피 데이터 처리         │
│  "바리스타가 커피 비즈니스 로직 담당"                         │
│                                                             │
│  controllers: [CoffeesController] ◄── CoffeesService 주입   │
│           ↓                                                 │
│  "손님이 커피 주문하면 바리스타에게 전달"                      │
│                                                             │
│  exports: [CoffeesService] ────► 다른 모듈에서 사용 가능     │
│  "주문부서에서도 우리 바리스타 쓸 수 있어요"                   │
└─────────────────────────────────────────────────────────────┘

실전 예제

예제 1: 기본 모듈 구조

// coffees.module.ts
import { Module } from '@nestjs/common';
import { CoffeesController } from './coffees.controller';
import { CoffeesService } from './coffees.service';

@Module({
  controllers: [CoffeesController],
  providers: [CoffeesService],
})
export class CoffeesModule {}

예제 2: 다른 모듈 가져오기 (imports)

// coffees.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Coffee } from './entities/coffee.entity';
import { CoffeesController } from './coffees.controller';
import { CoffeesService } from './coffees.service';

@Module({
  imports: [TypeOrmModule.forFeature([Coffee])], // 👈 TypeOrm 기능 가져오기
  controllers: [CoffeesController],
  providers: [CoffeesService],
})
export class CoffeesModule {}

예제 3: 서비스 내보내기 (exports)

// coffees.module.ts
@Module({
  controllers: [CoffeesController],
  providers: [CoffeesService],
  exports: [CoffeesService], // 👈 다른 모듈에서 사용 가능하게
})
export class CoffeesModule {}

// orders.module.ts
@Module({
  imports: [CoffeesModule], // 👈 CoffeesModule 가져오기
  controllers: [OrdersController],
  providers: [OrdersService], // OrdersService에서 CoffeesService 주입 가능!
})
export class OrdersModule {}

예제 4: 루트 모듈 (AppModule)

// app.module.ts
import { Module } from '@nestjs/common';
import { CoffeesModule } from './coffees/coffees.module';
import { UsersModule } from './users/users.module';

@Module({
  imports: [CoffeesModule, UsersModule], // 👈 하위 모듈들 연결
  controllers: [],
  providers: [],
})
export class AppModule {}

자주 하는 실수

❌ 실수 1: imports에 서비스 넣기

// 잘못된 예시
@Module({
  imports: [CoffeesService], // ❌ 서비스는 imports에 넣으면 안됨!
})

// 올바른 예시  
@Module({
  providers: [CoffeesService], // ✅ 서비스는 providers에!
})

❌ 실수 2: export 안 하고 다른 모듈에서 사용하려 함

// coffees.module.ts
@Module({
  providers: [CoffeesService],
  // exports 없음! ❌
})

// orders.module.ts
@Module({
  imports: [CoffeesModule],
  providers: [OrdersService], // OrdersService에서 CoffeesService 주입 시도
})
// 에러: CoffeesService를 찾을 수 없음!

// 해결: CoffeesModule에서 export 추가
@Module({
  providers: [CoffeesService],
  exports: [CoffeesService], // ✅ export 해줘야 다른 모듈에서 사용 가능
})

❌ 실수 3: ES6 import만 하고 @Module imports 안 함

// orders.module.ts
import { CoffeesModule } from '../coffees/coffees.module'; // ES6 import만 함

@Module({
  // imports: [CoffeesModule], // 👈 이게 없으면!
  providers: [OrdersService],
})
// 에러: OrdersService에서 CoffeesService 주입 불가!

💡 ES6 import는 코드 참조용, @Module imports는 DI 연결용

 

개념 한 줄 요약
@Module 관련 기능을 묶는 조직 단위
imports 다른 모듈 기능 빌려쓰기
providers 내부 서비스 등록
controllers HTTP 요청 처리 창구
exports  외부에 공개할 것

 

참고 자료

반응형
Comments