[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 1. 개요 |
[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 2. TCP |
[NestJS]내장된기능활용해마이크로서비스구현하기 - 3. MQTT |
[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 4. Kafka |
Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea
docs.nestjs.com
(기본적으로 저는 도커 컨테이너로 각 마이크로서비스를 구현하고 이들을 도커 컴포즈로 묶어서 실행하여 실습을 진행했습니다.)
실습은 위와 같은 구조를 이용했습니다. 먼저 HTTP 요청을 받아서 다른 마이크로서비스에 TCP 요청을 보낼 수 있는 A 서버를 만들었습니다. 또 A 서버로부터 TCP 요청을 받고 응답을 반환할 B 서버도 만들었습니다.
A 마이크로서비스 서버 (Client)
# main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
해당 서버는 HTTP 프로토콜을 이용해야합니다. 또한 TCP 프로토콜은 요청만 보낼 것이고 외부에서 들어오는 TCP 요청은 받지 않을 것이므로 단순 HTTP 프로토콜 이용 방식으로 실행했습니다.
# app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ClientsModule, Transport } from '@nestjs/microservices';
@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.TCP,
options: {
host: 'B 서버 도커 컨테이너명',
port: 'B 서버 TCP 통신에 사용할 포트',
},
},
]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }
imports에는 내가 TCP 요청을 보낼 때 관련된 정보를 기입합니다. name은 service코드에 주입할 때 사용할 이름을 설정하는 것이고 transport는 사용할 프로토콜을 지정하는 부분입니다. 그리고 options에는 요청을 보낼 마이크로서비스 서버의 정보를 기입하면 됩니다. 저는 위에서 언급했듯 도커 컨테이너를 활용해 환경을 구성했기 때문에 위와 같이 설정했습니다.
# app.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
import { AppService } from './app.service';
import { Observable } from 'rxjs';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('sum')
getSum(@Query('numbers') numbers: string): Observable<number> {
return this.appService.accumulate();
}
}
HTTP GET 메서드를 하나 간단하게 설정했습니다.
# app.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { Observable } from 'rxjs';
@Injectable()
export class AppService {
constructor(
@Inject('MATH_SERVICE') private client: ClientProxy,
) {}
accumulate() {
const pattern = { cmd: 'sum' };
const payload = [1, 2, 3];
return this.client.send<number>(pattern, payload);
}
}
HTTP GET 요청을 받았을 때 실행될 실제 로직입니다. 요청은 pattern과 payload 두 가지로 구성됩니다. pattern은 어떻게 호출할지에 대한 내용이고 payload는 전달할 데이터입니다. 즉 요청을 받을 마이크로서비스에는 해당 pattern을 받을 때 실행되는 로직이 구현되어 있어야합니다.
B 마이크로서비스 서버
# main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule, {
transport: Transport.TCP,
options: {
host: 'B 서버 도커 컨테이너명',
port: 'B 서버 TCP 통신에 사용할 포트',
},
});
await app.listen();
}
bootstrap();
해당 서버는 A 서버에서 TCP 프로토콜을 이용한 요청에 대한 응답을 하는 마이크로서비스입니다. 그러므로 위와 같이 마이크로서비스로 설정했습니다.
# app.controller.ts
import { AppService } from './app.service';
import { MessagePattern } from '@nestjs/microservices';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@MessagePattern({ cmd: 'sum' })
accumulate(data: number[]): number {
return (data || []).reduce((a, b) => a + b);
}
}
위에서 언급한 A 서버의 app.service.ts 코드의 this.client.send(pattern, payload); 부분과 관련된 부분입니다. 이때 pattern으로 { cmd : 'sum' }을 이용한다고 했었습니다. 즉, 해당 pattern을 요청하면 어떻게 응답할 것인지를 구현한 부분이 바로 이 부분입니다. 이 과정에서 request-respone 스타일을 사용할 것인지 event-based 스타일을 사용할 것인지에 따라 다른 데코레이터를 사용할 수 있습니다. 일단 저는 request-response 스타일을 사용하기 위해 @MessagePattern 데코레이터를 사용했습니다. (그리고 단순하게 구현하기 위해 service 코드를 따로 작성하지 않고 controller에 로직을 바로 구현했습니다)
실행 결과
A 서버에 /sum GET 요청을 보냈더니, 결과적으로 6이라는 결과값을 반환받았습니다. 이는 A 서버에 들어간 HTTP(GET)요청이 처리되고 이후에 A 서버가 B 서버로 TCP 요청을 보냈고, 해당 요청을 통해 B 서버에서 [1,2,3]이 모두 더해진 6이라는 값이 최종적으로 응답으로 반환되었음을 알 수 있습니다.
이를 통해 TCP 프로토콜과 request-response 스타일의 마이크로서비스 동작 방식에 대해 이해할 수 있었습니다.
'백엔드 > NestJS' 카테고리의 다른 글
[NestJS] 컨트롤러에서 브레이크 포인트 안 걸릴 때 체크해야할 것들! ( 동적 경로, 정적 경로, route parameter ) (0) | 2024.11.25 |
---|---|
[NestJS]Jest를 이용해 테스트하자 - 1. 유닛 테스트(Unit Testing) (0) | 2024.11.12 |
[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 4. Kafka (0) | 2024.11.04 |
[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 3. MQTT (0) | 2024.11.04 |
[NestJS]내장된 기능 활용해 마이크로서비스 구현하기 - 1. 개요 (0) | 2024.11.02 |