본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Node.js/Nestjs (Nest.js)

Nestjs 프레임워크 서버(일반 웹소켓 사용하기, websocket, socket.io 말고)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2023. 5. 25.

 
Nest.js에서 웹소켓 서버를 구현하기 위한 대부분의 방법은 socket.io를 사용하는 구성 방식으로 되어 있습니다.
소켓io로 구성을 하게되면, 일반적인 웹소켓 요청으로는 데이터를 송수신 할 수 없기에..
단순하게 구성하기 위해서는 다른 방법을 사용 해 주어야 합니다.
 
먼저 웹소켓(websocket) 서버 구현을 위해서 아래 2개의 라이브러리를 추가하여 줍니다.

#1. 이건 기본으로 설치하는거
yarn add @nestjs/websockets

#2. 요녀석이 일반 웹소켓 서버를 위해 필요한거
yarn add @nestjs/platform-ws

 
설치가 되고 난 이후에 가장먼저 해야 할 일은 main.ts 파일에 일반 웹소켓 서버 기능을 쓰겠다고 설정하는 것 입니다.
* 대상 : 메인 파일(부트스트랩 파일)

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

import { WsAdapter } from '@nestjs/platform-ws';  //여기!!

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useWebSocketAdapter(new WsAdapter(app));  //Nestjs에게 어떠한 웹소켓 기능을 쓸지 적용!
  await app.listen(3000);
}
bootstrap();

 
이렇게 하고 난 뒤에, 웹소켓 기능과 관련된 핸들러를 작성하여 주면 됩니다.
하도...자기 자신에게 돌아오는 에코(echo)로 된 예제가 난무하여 간단하게 접속한 모든 인원에게 응답하는 기능을 작성하여 보았습니다.
* 대상 : 웹소켓 응답을 담당하는 핸들러 파일

import { WebSocketGateway, SubscribeMessage, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';

@WebSocketGateway({
  cors: {
    origin: '*',
  },
  path : '응답경로!'
})
export class WebsocketHandler implements OnGatewayConnection, OnGatewayDisconnect {
  
  private wsClients : Array<any> = [];

  afterInit() : void {
    console.log('준비완료');
  }

  //OnGatewayConnection를 오버라이딩
  //1. 사용자가 처음으로 접속하면
  async handleConnection(client: any,  ...args: any[]) {
    this.wsClients.push(client);  //2. 배열에 사용자를 담아줍니다.
    for(let item of args){
      console.log(item?.url)  //여기에 query가 있습니다.
    }
  }

  //OnGatewayDisconnect를 오버라이딩
  //1. 사용자가 종료하면
  async handleDisconnect(client: any)  {
    for (let i = 0; i < this.wsClients.length; i++) {
      if (this.wsClients[i] === client) {    //2. 배열을 뒤져서 해당 데이터를 제거 합니다.
        this.wsClients.splice(i, 1);
        break;
      }
    }
  }

  /* 메시지에 event라는 항목이 필수로 존재해야 합니다. 
  { 
    "event": "정의한키",
    "data": "데이터"
    }
  */
  @SubscribeMessage('정의한키') //1. 정의한 키값이 존재한 메시지가 도착하면,
  handleEvent(client, message: any): void {
    for (let c of this.wsClients) {  //2. 배열에서 클라이언트 객체를 가져와 정의한 행동을 합니다.
      c.send(JSON.stringify({"result":"succ", ...message}));
    }
  }
  
}

 
 
어렵지 않지만 설명이 필요한 코드 입니다.
가장 처음에 선언한 WebSocketGateway 데코레이터path는 요청하는 경로 입니다.
ws를 사용하는 클라이언트는 서버에서 정의한 path에 대해서 url을 확인하여 접속을 해야 합니다.

///서버 코드...
@WebSocketGateway({
  cors: {
    origin: '*',
  },
  path : 'chatting'  //만약 chatting으로 된 경로값이 있다면 요청은 아래와 같이 해야 합니다.
})
export class WebsocketHandler implements OnGatewayConnection, OnGatewayDisconnect {
  //생략..
}


///클라이언트 전송 코드...
let 소켓 = new WebSocket("ws://127.0.0.1/chatting");

 
다음으로 서버에서 수신하는 SubscribeMessage 데코레이터 부분 입니다.
Nestjs도 최근 트렌드에 맞게 json 형식의 데이터를 수신하며, 따라서 전송하는 데이터는 text 이지만 꼭 반드시 json 형식을 취해야 합니다.
해당 json 형식에서 event 라는 필드에 서버에서 정의한 필드가 맞아야 데이터가 송수신 되는 것을 볼 수 있습니다.

@WebSocketGateway({
  cors: {
    origin: '*',
  },
  path : 'chatting'
})
export class WebsocketHandler implements OnGatewayConnection, OnGatewayDisconnect {

  //생략....

  @SubscribeMessage('data') //1. 정의한 키값이 존재한 메시지가 도착하면,
  handleEvent(client, message: any): void {
    for (let c of this.wsClients) {  //2. 배열에서 클라이언트 객체를 가져와 정의한 행동을 합니다.
      c.send(JSON.stringify({"result":"succ", ...message}));
    }
  }
  
}

 
위 내용을 아래 사진으로 첨부 하였습니다.

 
이러한 방식을 통해서 event에 있는 여러 타입을 통해 다양한 종류의 메시지 처리가 손쉽게 가능 합니다.
 
Nestjs 프레임워크 서버에서 소켓IO를 쓰지 않고 일반 웹소켓 기능을 사용하는 방법에 대해 정리하여 보았습니다.
궁금한점 또는 틀린부분은 언제든 연락주세요! 😁

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글