(Node.js) Nestjs + MSA 기반 서버 구축 (1)

2025. 6. 8. 13:00Node.js

반응형

● 순서
 

  1. 요지
  2. 환경 설정 및 Lib 설치
  3. 코드 구현
  4. 테스트 통신
  5. 마무리

 

1. 요지

우연히 NestJS + MSA + MongoDB를 기반으로 한 서버를 docker-compose로 구축할 수 있는 기회가 생겼었다
그래서 해당 구축한 내용을 기록하기 위해 작성해보고자 한다
단, 해당 내용이 아닌 다른 내용으로 기초 구축 단계만 작성하며, 단계 별로 나눠서 연동하고 부분적으로 업로드할 예정
 

MSA란?

- 마이크로서비스 아키텍처(Microservices Architecture)의 약자로 하나의 애플리케이션을 여러 개의 독립적인 서비스로 분리하여 운영하는 것을 의미한다
- NestJS는 MSA를 기본적으로 지원하여 서비스 간의 통신, API Gateway, 메시지 큐(RabbitMQ, Kafka)와의 통합 등을 쉽게 구현 가능
- 독립적인 개발, 배포, 확장이 될 수 있어서 유지보수 및 유연성에 편리
 

MSA의 구성 및 Gateway 예제

 
 

서버 구성

- 서버 구성은 다음과 같다

  1. Gateway 서버 - 모든 API의 진입점
    • 단일 진입점을 통해서 클라이언트 측에서 서비스 간의 관리와 네트워킹을 간소화
    • 보안 상의 위협으로부터 서비스를 보호
    • 서비스들 사이에서 요청을 분산하여 로드 밸런싱을 수행하여 서비스에 균등한 트래픽 분산을 제공하고 서비스의 가용성과 성능을 최적화
    • API 관리 기능을 제공할 수 있습니다. API 버전 관리, 요청 및 응답의 변환, 캐싱, 로깅, 분석 등의 기능을 수행하여 개발자가 API를 효과적으로 관리하고 모니터링할 수 있도록 지원
    • 하나의 클라이언트 요청에 대해 여러 개의 서비스를 호출해야 하는 경우, Gateway 서버는 이러한 요청을 통합하여 단일 응답으로 반환하여, 클라이언트 측의 응답 처리를 간소화
  2. Board 서버 - 게시물 관련 CRUD

- TCP를 이용한 Nest Microservices

  • Nest에서 제공하는 라이브러리로 MSA를 구성

 

2. 환경 설정 및 Lib 설치

- 먼저 NestJS를 전역에 설치

# nestjs cli 전역 설치
npm install -global @nestjs/cli@latest

# 혹은
npm install -g @nestjs/cli@latest

 
- 구성할 서버(서비스) 명으로 구축 및 라이브러리 설치

# gateway 서비스 구축
nest new gateway

# gateway 라이브러리 설치
cd gateway
npm install @nestjs/microservices

# 프로젝트 root로 이동
cd .. 

# board 서비스 구축
nest new board
cd board
npm install @nestjs/microservices

 

설치 과정

 
`nest new gateway` 혹은 `nest new board` 를 입력하면 위와 같은 화면을 만날 수 있다
나는 npm을 사용하기 위해 npm를 선택!!
 

설치 완료

 
여기까지 성공했으면

cd gateway
npm run start:dev
npm 실행화면

그리고 http://localhost:3000으로 접속하면

웹 화면

이런 화면을 만날 수 있다~!!
 

3. 코드 구현

3-1. gateway 서버
gateway controller

- API 진입점을 정의

// gateway/src/app.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('boards')
  async getBoards() {
    return this.appService.getBoards();
  }

  @Post('board')
  async createBoard(@Body() data) {
    return this.appService.createBoard(data);
  }
}

 
gateway service

- 독립적인 서비스로 TCP 연결 후 통신 요청

// gateway/src/app.service.ts
import { Injectable } from '@nestjs/common';
import {
  ClientProxy,
  ClientProxyFactory,
  Transport,
} from '@nestjs/microservices';

@Injectable()
export class AppService {
  private boardClient: ClientProxy;

  constructor() {
    this.boardClient = ClientProxyFactory.create({
      transport: Transport.TCP,
      options: { host: '0.0.0.0', port: 4002 },
    });
  }

  getHello(): string {
    return 'Hello World!';
  }

  getBoards() {
    return this.boardClient.send({ cmd: 'get-boards' }, {});
  }

  createBoard(data: any) {
    return this.boardClient.send({ cmd: 'create-board' }, data);
  }
}

 
3-2. board 서비스
board main

- board에서도 TCP를 연결 설정

// board/src/main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      transport: Transport.TCP,
      options: { host: '0.0.0.0', port: 4002 },
    },
  );
  await app.listen();
}
bootstrap();

 
board controller
- gateway에서 send메서드로 요청된 일치한 메시지패턴을 응답
- 비즈니스 로직 메서드를 호출

// board/src/app.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @MessagePattern({ cmd: 'get-boards' })
  async getBoards() {
    return this.appService.findAll();
  }

  @MessagePattern({ cmd: 'create-board' })
  async createBoard(data: any) {
    return this.appService.create(data);
  }
}

 
board service
- controller에서 호출된 비지니스 로직을 구현

// board/src/app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  async findAll(): Promise<any[]> {
    // This should return a list of boards from the database
    // console.log('Fetching all boards');
    return [];
  }

  async create(data: any): Promise<any> {
    // This should create a new board in the database
    // console.log('Creating a new board with data:', data);
    return data;
  }
}

 
두 개의서버를 실행 후

npm run start:dev

 
 
- findAll 메서드나 create메서드에 가벼운 콘솔로 확인
- postman으로 통신 확인
 

localhost:3000 접속시
GET localhost:3000/boards