프로그래밍/Nest.js

Nest.JS Controller, Module, Service 의 관계

Terry Cho 2025. 4. 14. 15:16

Nest.JS에서 처음으로 소개되는 개념인 Controller, Service, Module의 개념에 대해서 알아보자. 

 

Controller

HTTP Request를 직접 받는 컴포넌트이다. 어떤 URI로 받을지 @Get,@Post,@Put,@Delete 등의 데코레이터로 어떤 HTTP Request를 받을지 결정한다. 

아래는 /users REST API를 정의한 간단한 예제인데

  • /users URI는 @Controller('users') 데코레이터에서 정의한다. 
  • @Get(':id')로 /users/{id}에 대한 요청 처리 로직을 정의하였다. 
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';

@Controller('users') // 기본 경로를 /users 로 변경
export class UsersController {

  @Post() // POST /users
  createUser(@Body() userData: any) {
    // 새 사용자 생성 로직
    console.log('Creating user:', userData);
    return { message: 'User created successfully', data: userData };
  }

  @Get() // GET /users
  findAllUsers() {
    // 모든 사용자 조회 로직
    console.log('Finding all users');
    // 예시 데이터 반환
    return [{ id: 1, name: '홍길동' }, { id: 2, name: '김철수' }];
  }

  @Get(':id') // GET /users/:id (예: /users/1)
  findOneUser(@Param('id') userId: string) {
    // 특정 ID의 사용자 조회 로직
    console.log('Finding user with ID:', userId);
    // 예시 데이터 반환
    return { message: `Details of user ${userId}`, data: { id: userId, name: '조회된 사용자' } };
  }

 

Service

Controller가 HTTP로 부터 요청을 받고, 응답 메시지를 전달(처리가 아니라)할 수 있도록 인터페이스 역할을 해준다면, Service는 실제적인 비즈니스 로직을 담고 있는 부분이다. 즉 Controller에서는 REST 요청을 받아서 JSON으로 만든후에, Service에 전달해서 Service에서 DB에 저장하는 역할같은 것을 한다. 

 

대략적인 예시 코드를 보면, 아래는 create 라는 메서드로 사용자를 create하는 시나리오인데, 앞에서 작성한 createUser가 이 UserService의 create 메서드를 호출하는 구조로 구현한다. 

interface CreateUserDto {
  name: string;
  email?: string;
}

@Injectable() // Marks the class as a Provider that can be injected
export class UsersService {
  // In-memory array to simulate a database table for users
  private users: User[] = [
    { id: 1, name: '홍길동', email: 'gildong@example.com' },
    { id: 2, name: '김철수', email: 'chulsoo@example.com' },
  ];
  private nextId = 3; // Simple counter for generating next user ID

  /**
   * Creates a new user based on the provided data.
   * Corresponds to the logic needed for a POST /users request.
   * @param userData - The data for the new user (name, email, etc.).
   * @returns The newly created user object.
   */
  create(userData: CreateUserDto): User {
    console.log('Service: Creating user with data:', userData);
    const newUser: User = {
      id: this.nextId++, // Assign a new ID and increment the counter
      ...userData, // Spread the properties from the DTO
    };
    this.users.push(newUser); // Add the new user to the in-memory array
    console.log('Service: User created:', newUser);
    return newUser; // Return the created user
  }

 

Module

그러면 UsersService와 UsersController는 어떻게 연결할까? 이 기능을 해주는 것이 Module이다. 아래는 UsersController와 UsersService를 실제적으로 묶은 Module 이다.   

@Module({
  // controllers: An array of controllers that should be instantiated in this module.
  controllers: [UsersController],

  // providers: An array of providers (services, factories, etc.) that will be
  // instantiated by the Nest injector and that may be shared at least across this module.
  providers: [UsersService],
})
export class UsersModule {}

그러면 REST 마이크로 서비스가 여러개 일때 (즉 Module이 여러개일때), 소스 디렉토리 구조는 어떻게 해야 할까?

서비스 별로 디렉토리 (users, produtcs etc)를 만들고 그안에 각각 Module, controller, service 들을 배치한다. 

src/
├── app.module.ts             # 애플리케이션 루트 모듈
├── app.controller.ts         # 루트 컨트롤러 (선택 사항)
├── app.service.ts            # 루트 서비스 (선택 사항)
├── main.ts                   # 애플리케이션 시작점 (bootstrap)
│
├── users/                    # '사용자' 기능 모듈 디렉토리
│   ├── dto/                  # 데이터 전송 객체 (Data Transfer Objects)
│   │   ├── create-user.dto.ts
│   │   └── update-user.dto.ts
│   ├── entities/             # 데이터베이스 엔티티 (예: TypeORM)
│   │   └── user.entity.ts
│   ├── users.module.ts       # Users 기능 모듈 (Canvas의 코드)
│   ├── users.controller.ts   # Users 컨트롤러
│   ├── users.service.ts      # Users 서비스
│   └── users.service.spec.ts # 서비스 유닛 테스트
│
├── products/                 # '제품' 기능 모듈 디렉토리
│   ├── dto/
│   │   └── create-product.dto.ts
│   ├── entities/
│   │   └── product.entity.ts
│   ├── products.module.ts
│   ├── products.controller.ts
│   ├── products.service.ts
│   └── products.controller.spec.ts
│
├── auth/                     # '인증' 기능 모듈 디렉토리
│   ├── dto/
│   ├── guards/               # 인증 가드
│   ├── strategies/           # Passport 전략 등
│   ├── auth.module.ts
│   ├── auth.controller.ts
│   ├── auth.service.ts
│   └── jwt.strategy.ts
│
└── shared/                   # 여러 모듈에서 공통으로 사용하는 모듈/유틸리티 (선택 사항)
    ├── database/             # 데이터베이스 연결 모듈
    │   └── database.module.ts
    └── common/               # 공통 헬퍼, 데코레이터 등
        └── exceptions/
            └── http-exception.filter.ts

'프로그래밍 > Nest.js' 카테고리의 다른 글

Nest.JS DTO,DAO and Pojo  (0) 2025.04.14