nestjs 프레임워크에서는 소규모의 독립적인 서비스(microservices)의 기능 구현을 위해 마이크로서비스(microservices)라는 모듈을 제공하고 있습니다.
해당 마이크로서비스(microservices) 모듈을 활용하여 사용 할 수 있는 대표적인 기능이 mqtt 기능입니다.
물론 mqtt 기능을 사용하기 위해서는 mqtt 서버가 갖추어져 있어야 합니다. : - )
* mqtt서버는 래빗mq, 모스키토, eclipse-mosquitto 같은 서버를 사용하면 됩니다.
역시나 처음 서비스 사용을 위해서는 모듈을 설치하여 줍니다.
//마이크로서비스
npm install @nestjs/microservices
//mqtt서버
npm install mqtt
nestjs에서 사용할 수 있는 마이크로서비스(microservice)는 mqtt 말고도 레디스(redis), kafka, NATS같은 서비스 연동도 가능 합니다.
아무튼..이렇게 라이브러리를 설치한 다음에 맨 처음 메인파일을 변경 해 줍니다!
기본 메인파일은 HTTP서버로서의 역할을 하기 때 문 입니다.
* 파일이름 : main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions } from '@nestjs/microservices';
import { Transport } from '@nestjs/microservices/enums';
import { AppModule } from './app.module';
async function bootstrap() {
//NestFactory에서 사용하는 함수가 createMicroservice입니다! 기존의 create 아닙니다!
//제네릭도 잘 보셔야 합니다! MicroserviceOptions 입니다!
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule,{
transport: Transport.MQTT,
options: {
host: 'localhost',
port: 1883,
}
});
app.listen();
}
bootstrap();
메인 파일을 이렇게 변경하게 되면 해당 어플리케이션은 서버의 역할이 아니라 클라이언트의 역할을 하게 됩니다.
즉 해당 어플리케이션은 mqtt서버에 접속해서 메시지를 읽고 전달하는 역할을 하게 됩니다.
다음으로 모듈부분을 수정 합니다.
모듈은 mqtt서버의 기본 접속정보를 등록 할 수 있습니다.
가령 아이디, 비밀번호가 존재 한 다면 해당파트에서 등록을 해 줍니다.
* 파일이름 : 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: 'MY_MQTT_SERVICE', //* MY_MQTT_SERVICE : 의존성 이름
transport: Transport.MQTT,
options: {
host: 'localhost',
port: 1883,
clientId : 'id',
password : 'password'
}
}
]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
constructor() {}
}
이제 실제 연동하는 부분 입니다.
연동은 메시지를 수신하고 전송하는 기능으로 구현 하였습니다.
* 파일이름 : app.controller.ts
import { Controller, Inject } from '@nestjs/common';
import { MessagePattern, Payload as pd, ClientProxy } from '@nestjs/microservices';
import {take} from 'rxjs';
@Controller()
export class AppController {
constructor(@Inject('MY_MQTT_SERVICE') private client : ClientProxy) { //* MY_MQTT_SERVICE : 의존성 이름
setTimeout(() => { //3초뒤에 메시지를 발송하게 하였습니다.
const data = {number : Math.random(), text : AppController.name};
this.client.send('Korean',data).pipe(take(1)).subscribe();
}, 3000);
}
@MessagePattern('World') //구독하는 주제1
모두받기(@pd() data){
console.log(data);
}
@MessagePattern('American') //구독하는 주제2
고유받기(@pd() data){
console.log(data);
}
}
이를 동작시킨 모습입니다.
MQTTX라는 응용프로그램을 통해서 서로 주고받는 기능을 확인 하였습니다.
* MQTTX : MQTT 프로토콜을 사용하는 응용 프로그램(카카오메신저같은)
World라는 주제에 대해서 MQTTX 프로그램으로 데이터를 전송하고, nestjs에서도 받은 모습 입니다.
해당 어플리케이션은 mqtt에 대해서 동작을 하기 때 문에 서버의 기능 보다는 클라이언트의 기능이 좀 더 강력 합니다.
우리가 사용하는 브라우저(크롬, 엣지, 파이어폭스 등)에서는 mqtt를 사용 할 수가 없습니다.
그러므로 이를 위해서 http 서버의 기능을 만들어준 다음에, http 요청 후에 mqtt로 다시 요청을하게 하고, 해당 결과를 보여주는 방식으로 개발이 되어야 합니다.
HTTP요청 → HTTP수신 → MQTT요청 → MQTT수신 → HTTP응답
위 mqtt 어플리케이션에서 http서버를 사용하려면 아래처럼 메인파일에 2개의 앱 설정을 해 주어야 합니다.
* 파일이름 : main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions } from '@nestjs/microservices';
import { Transport } from '@nestjs/microservices/enums';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { http모듈 } from './http모듈';
async function bootstrap() {
//#1. mqtt 어플리케이션으로 사용
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule,{
transport: Transport.MQTT, //사용할 종류
options: {
host: 'localhost',
port: 1883,
}
});
app.listen();
//#2. http서버로 사용
const httpApp = await NestFactory.create<NestExpressApplication>(http모듈);
await httpApp.listen(8080);
}
bootstrap();
nestjs에서 동작할 때 2개의 모듈을 동작하게 하였습니다.
1개는 기존에 만들어 두었던 mqtt와 관련된 모듈이며, 나머지 1개는 새로이 만들어준 http관련 모듈 입니다.
* 이름 : "http모듈" 클래스
http와 관련된 모듈을 새로 추가하여 줍니다.
http 모듈은 이전부터 만들어온 방식으로 구현하면 됩니다.
* 파일이름 : http모듈.ts
import { Module } from '@nestjs/common';
import { AppModule } from './app.module';
import { http컨트롤 } from './http컨트롤';
@Module({
imports: [
AppModule //mqtt 모듈을 가져 옵니다.
],
controllers: [http컨트롤],
providers: [],
})
export class http모듈 {}
새로 만든 http모듈에게 응답용 컨트롤러를 새로 붙여 줍니다.
해당 컨트롤러 또한 기존 방식처럼 만들어주면 됩니다.
* 파일이름 : http컨트롤.ts
import { Request, Response } from 'express';
import { Controller, All, Res, Req, HttpStatus,Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import {take} from 'rxjs';
@Controller()
export class http컨트롤 {
constructor(@Inject('MY_MQTT_SERVICE') private client : ClientProxy) {
}
@All('web')
async normal(@Req() req: Request, @Res() res: Response) {
//get 방식으로 데이터를 받아서 data 라는 키 값으로 mqtt서버로 전송하게 하였습니다.
console.log(req.query)
await this.client.send('Korean',{data:req.query}).pipe(take(1)).subscribe();
res.status(HttpStatus.OK).send({ yourRequest: req.query });
}
}
web이라는 get방식의 요청이 오면, mqtt 서버에게 내용을 전달하게 하였습니다.
하지만 해당 코드를 동작하면 오류가나는데, "MY_MQTT_SERVICE" 라는 의존성을 받지 못한 오류가 발생하게 됩니다.
해당 객체는 AppModule클래스(app.module.ts 파일) 에만 존재하기 때문 입니다.
그러므로 기존의 AppModule클래스(app.module.ts 파일) 에 존재하는 mqtt 설정을 가져오기 위해서 AppModule을 아래와 같이 수정 해 줍니다.
* 파일이름 : app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ClientsModule, Transport } from '@nestjs/microservices';
const clients = ClientsModule.register([
{
name: 'MY_MQTT_SERVICE', //* MY_MQTT_SERVICE : 의존성 이름
transport: Transport.MQTT,
options: {
host: 'localhost',
port: 1883
}
}
]);
@Module({
imports: [
clients
],
controllers: [AppController],
providers: [AppService],
exports : [clients] //다른 모듈에서 쓸 수 있게 출력!
})
export class AppModule {
constructor() {}
}
위 코드는 간단하게 export를 활용한 예제 이므로 본인 프로젝트의 구성에 맞게 모듈을 다시 구성하는 것이 좋습니다.
이제 GET방식으로 접속하여 봅니다!
http의 요청을 받아서 mqtt 서버에게 데이터를 다시 전달하는 것을 확인 할 수 있습니다!
이처럼 nestjs에서는 기능을 모듈 단위로 분리할 수 있기 때 문에 나중에 해당 기능에 대해서 유지보수할 때 매우 편리하게 할 수 있습니다.
위 내용에 사용된 소스코드는 아래 제 깃허브에서 받아볼 수 있습니다.
https://github.com/TaeSeungRyu/NestProject/tree/main/step16
공부하면 할 수록 재미있고 즐거운 nestjs!!!
궁금한점 또는 틀린부분은 언제든 연락 주세요!
'Node.js > Nestjs (Nest.js)' 카테고리의 다른 글
NestJS SSE (Server-Sent Events) (0) | 2023.07.19 |
---|---|
Nestjs 프레임워크 서버(일반 웹소켓 사용하기, websocket, socket.io 말고) (2) | 2023.05.25 |
Nestjs 프레임워크 서버(log, winston) -16 (2) | 2022.10.04 |
Nestjs 프레임워크 서버(emitter, rxjs, schedule) -15 (0) | 2022.09.22 |
Nestjs 프레임워크 서버(Mongodb, database) -14 (0) | 2022.09.16 |
댓글