WebSocket이란?

WebSocket(ws) 이란 http 프로토콜과 같이 프로토콜의 일종이며, 클라이언트와 서버(브라우저와 서버)를 연결하고 언제든 양방향(주고 받는) 통신 또는 데이터 전송이 가능하도록 하는 기술입니다.

이번 게시글에서는 WebSocket 프로토콜을 기반으로 구축된 Socket.io 라이브러리를 이용하여 WebSocket 서버를 구성 후 연결 테스트를 해보겠습니다.

 

역시나 NestJS 의 공식문서에 설명이 잘 되어 있어 이를 참고했습니다.

https://docs.nestjs.com/websockets/gateways#gateways 

 

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 Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

Socket.io 란?

Socket.io enables real-time, bidirectional and event-based communication. It works on every platform, browser or device, focusing equally on reliability and speed.

Socket.io는 node.js 기반으로 만들어진 기술로, 거의 모든 웹 브라우저 및 모바일 장치를 지원하는 실시간 웹 어플리케이션 지원 라이브러리입니다. 

NestJS 서버 설정

먼저 프로젝트를 생성 후 이벤트 모듈, 게이트웨이 파일을 생성하겠습니다.

# 프로젝트 생성
$ nest new chat-project
# events 모듈 생성
$ nest g mo events
# events 게이트웨이 생성
$ nest g ga events

이어서 필요한 패키지를 설치하겠습니다.

$ npm i --save @nestjs/websockets @nestjs/platform-socket.io
$ npm i --save-dev @types/socket.io

위의 명령으로 실행해 만들어진 Events 모듈은 다음과 같이 자동으로 app 모듈에 임포트되어 있고 Events 게이트웨이는 Events 모듈의 프로바이더로 등록되어 있음을 확인하실 수 있습니다.

// src/app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { EventsModule } from './events/events.module';


@Module({
  imports: [EventsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
// src/events/events.module.ts

import { Module } from '@nestjs/common';
import { EventsGateway } from './events.gateway';


@Module({
  providers: [EventsGateway],
})
export class EventsModule {}

이번에는 Events Gateway 파일을 작성해보겠습니다. 이 파일은 실제로 소켓의 동작을 담당하는 중요한 부분입니다.

// src/events/events.gateway.ts

@WebSocketGateway(포트번호, {
  namespace: 'chat',
  cors: { origin: '*' },
})
export class EventsGateway
  implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
  constructor() {}
  
  @WebSocketServer() server: Server;
  private logger: Logger = new Logger('EventsGateway');

  @SubscribeMessage('events')
  handleEvent(@MessageBody() data: string): string {
    return data;
  }

  afterInit(server: Server) {
    this.logger.log('웹소켓 서버 초기화 ✅');
  }

  handleDisconnect(client: Socket) {
    this.logger.log(`Client Disconnected : ${client.id}`);
  }

  handleConnection(client: Socket, ...args: any[]) {
    this.logger.log(`Client Connected : ${client.id}`);
  }
}

기본적인 세팅은 위와 같습니다. 위에서부터 차례로 하나씩 살펴보겠습니다.

@WebSocketGateway(포트번호, {
  namespace: 'chat',
  cors: { origin: '*' },
})

포트번호와 네임스페이스는 원하는 값을 지정하면 됩니다. 서버 실행 시 서버주소:포트번호/네임스페이스 에서 웹소켓 서버가 실행됩니다.

프론트와 백엔드의 서버주소 혹은 포트번호가 다른 경우 CORS 에러가 발생합니다. 따라서 CORS 설정을 해줘야 합니다.

현재 설정 값은 모든 경우에 대해 CORS 허용하도록 설정해주었습니다.

afterInit(server: Server) {
  this.logger.log('웹소켓 서버 초기화 ✅');
}

웹소켓 서버가 실행되면 afterInit 함수가 실행되는데, 이 함수 내에서 필요한 기능을 수행할 수 있습니다.

server 변수를 사용하면 서버에 연결된 클라이언트들에게 이벤트를 발생시킬 수 있습니다.

handleDisconnect(client: Socket) {
   this.logger.log(`Client Disconnected : ${client.id}`);
}

handleConnection(client: Socket, ...args: any[]) {
   this.logger.log(`Client Connected : ${client.id}`);
}

클라이언트의 connect/disconnect 이벤트는 각각 handleConnection과 handleDisconnect 에서 처리가 가능합니다.

@SubscribeMessage('events')
handleEvent(@MessageBody() data: string): string {
  return data;
}

웹소켓 서버와 연결된 클라이언트에서 'events'를 발생시키면(emit), 서버에서 해당 이벤트를 읽어서 요청에 대한 응답을 할 수 있습니다.

handleEvent 함수 파라미터 값에 client: Socket 을 이용하면 해당 이벤트를 발생시킨 클라이언트를 특정할 수 있습니다.

위 코드에서는 클라이언트에서 emit('events', data) 를 응답한 것인데, 서버에서 반환해준 값을 클라이언트에서 응답으로 받을 수 있습니다. 

'라이브러리 & 프레임워크 > NestJS' 카테고리의 다른 글

[NestJS] Authentication  (0) 2022.11.29
Exception filter  (0) 2022.11.28
Validation  (0) 2022.11.28
Mapped Types  (0) 2022.11.28
[TypeORM] 마이그레이션  (0) 2022.11.27
복사했습니다!