[NestJS] NestJS에서 WebSocket 통신(@nestjs/websockets)에 대해

루나·2022년 10월 10일
1

사이드 프로젝트에서 채팅방 기능을 위해 Socket을 사용한다.
우선 NestJS에선 소켓을 쓰기위해 대표적으로 ws와 Socket.io를 사용해서 구현할 수 있다.
이중 레퍼런스도 많고 한층 더 추상화? 되었다고 생각되는 Socket.io를 사용하기로 했다.

import { Logger } from '@nestjs/common'
import { MessageBody, SubscribeMessage, WebSocketGateway, WebSocketServer, WsResponse } from '@nestjs/websockets'
import { Server } from 'socket.io'

interface loginMessage {
  user: string
}

interface roomMessage extends loginMessage {
  message: string
}

@WebSocketGateway(8080, { transports: ['websocket'] })
export class EventGateway {
  @WebSocketServer()
  server: Server
  logger = new Logger()

  @SubscribeMessage('ClientToServer')
  handleClientToServer(@MessageBody() { user }: loginMessage) {
    this.logger.log(`Login: ${user}`)
    this.server.emit('ServerToClient', `로그인 환영: ${user}`)
  }

  @SubscribeMessage('Room1')
  handleRoom1(@MessageBody() { user, message }: roomMessage): WsResponse {
    this.logger.log(`Client: ${user} Message: ${message}`)
    this.server.emit(`${user}'s AlertHandle`, 'new!')
    // this.server.emit('Room1', `${user}: ${message}`) // Room1을 구독하고 있는 전체에게 emit (broadcast)
    // return `${user}: ${message}` // Room1으로 요청을 보낸 특정 클라이언트에게만 Room1으로 emit
    return { event: 'Room1All', data: `${user}: ${message}` } // event로 emit
  }
}

서버측에서 클라이언트로 다시 메시지를 전송하는 방법으로 3가지가 있다.

1. this.server.emit('event', data)

Socket.io에서 기본적으로 제공해주는 방식으로 event로 emit을 날려 event를 Listen(on) 하고있는 모든 클라이언트에게 메시지를 보낸다.


정상적으로 해당 방에 존재하는(on 하고 있는) 모든 사람에게 메시지를 전송했다.

2. return data

NestJS에서 Gateway로 만든 함수에선 return을 이용해서도 메시지를 전송할 수 있었다.
여기서 return으로 처리가 가능하려면 Client측에서도 콜백함수를 열어줘야한다.

// client code
                                        //이쪽으로 return이 넘어오는거!!
socket.emit('events', { name: 'Nest' }, (data) => console.log(data));



그저 클라이언트 측에서 보낸 emit에 대한 응답을 전송하며 이 응답은 클라이언트에서 사용한 emit의 콜백 함수로 return된다. 따로 특정 이벤트에 emit을 날리진 않았다.

3. return { event, data } (Multiple Responses?)

뭔가 return으로도 특정 이벤트에 대한 응답을 보낼 수 있도록 Nestjs쪽에서 제공해주지 않을까? 하고 찾아다니다 공식 문서에 있는 Multiple Responses를 찾게 된다.

특정 event를 따로 지정할 수 있다는 점으로 2번과는 다르긴 하다.
하지만 결국 이 방법도 모든 클라이언트에게 emit을 보내진 않았고 요청을 보낸 클라이언트에게만 emit이 전송되는 것을 확인했다.
공식 문서의 설명을 봤을땐 뭔가를 Multiple하게 보낸다는 것 같은데... 달라지는 점은 event를 재정의해서 보낼 수 있다는 점 밖에 찾지 못했다.


전혀 All이 아닌 모습... 분명 Multiple Responses라고 적은 것에는 이유가 있을 것 같은데 뭔지 찾지 못했다..


결론은 return을 쓰는게 아니라 server.emit(boradcast)을 사용해서 Socket.io 객체의 메소드를 사용하는 방법으로 채팅방에 있는 모두에게 메시지를 전송시키도록 구현하게 될 것 같다.

return을 사용하는 방식은 event를 다시 적지 않아도 되고 간편하고 return type도 확인할 수 있었지만 요청을 보내왔던 클라이언트에게만 emit을 보내기 때문에 1:1 통신 시나리오에서만 사용할 수 있을 것 같다.
분명 다른 방법이 있을 것만 같지만 찾지 못했다... Multiple Response라고 명명한 의미를 잘 찾지 못해 아쉬웠다. 콜백에 대한 응답 + 특정 이벤트에 대한 응답을 보낼 수 있는 것을 두고 Multiple이라고 칭한 것일까..?

profile
백엔드 개발자

0개의 댓글