Search

웹소켓

WebSocket이란?

HTTP는 클라이언트가 요청하면 서버가 응답하는 구조이다.
반면 WebSocket은 클라이언트 서버 간에 양방향 통신이 가능하게 해주는 프로토콜이다.
서버가 클라이언트에게 실시간으로 메세지를 전송한다.
연결을 유지하며 데이터를 주고받는다. (HTTP보다 빠르다)

NestJS에서의 WebSocket

NestJS는 @nestjs/websockets 패키지를 설치하여 WebSocket을 쉽게 사용할 수 있게 해준다.
@WebSocketGateway 데코레이터를 통해 해당 클래스를 WebSocket 서버로 등록해준다.
@WebSocketGateway(port?: number, options?: GatewayOptions) export class ExampleGateway { }
TypeScript
복사
옵션
설명
예시
port
게이트웨이가 바인딩될 포트 번호 생략 시 HTTP 서버와 같은 포트를 사용한다.
@WebSocketGateway(3001)
namespace
특정 namespace로 클라이언트를 구분한다. 클라이언트들이 다른 경로(/chat, /notification 등)로 접속하게끔 나누는 단위
@WebSocketGateway({ namespace: '/chat' })
cors
socket.io 서버 CORS 설정을 할 수 있다. NestJS HTTP 서버의 CORS 설정과는 별개이다.
@WebSocketGateway({ cors: { origin: '*' } })
transports
클라이언트 서버 통신 방식 설정 (websocket, polling 등)
@WebSocketGateway({ transports: ['websocket'] })
path
커스텀 path로 WebSocket 서버를 노출할 수 있음
@WebSocketGateway({ path: '/ws' })

socket.io 서버의 옵션

NestJS는 WebSocket을 지원할 때 내부적으로 socket.io 를 사용한다. @WebSocketGateway 데코레이터의 옵션으로 들어가는 cors설정은 socket.io 서버 생성자에 전달되는 것이다.
@WebSocketGateway({ cors: { origin: '*' } }) 위 코드는 const io = new Server(httpServer, { cors: { origin: '*' } }); 이 코드와 같다.
TypeScript
복사

transports 옵션

transports 옵션에는 크게 polling과 websocket이 있다.
기본 옵션은 ['polling', 'websocket'] 으로 처음에는 polling으로 시작해서 가능하면 websocket으로 업그레이드하는 것이다.
만약 웹소켓만 쓰고 싶다면 [’websocket’]으로 polling만 할거라면 [’polling’]으로 설정하면 된다.
방화벽이나 프록시 문제로 웹소켓이 연결이 안 될 수도 있어 운영단계에서는 보통 기본 옵션을 사용한다.

연습 예제 코드

import { ConnectedSocket, MessageBody, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, WebSocketGateway, WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; // ExampleGateway를 WebSocket 서버로 등록 // 내부적으로 socket.io 서버 인스턴스를 생성 @WebSocketGateway({ namespace: '/example', transports: ['websocket'], cors: { origin: '*', }, }) export class ExampleGateway implements OnGatewayConnection, OnGatewayDisconnect { // Gateway 클래스에 Socket.IO의 서버 인스턴스를 주입해주는 데코레이터 // 클라이언트에게 직접 이벤트를 보내는 등 작업을 수행 @WebSocketServer() io: Server; handleConnection(client: Socket): any { const data = client.handshake.query; console.log(`client 연결 : ${client.id}, message: ${data.name}`); } handleDisconnect(client: Socket): any { console.log(`client 연결 끊김 : ${client.id}`); } @SubscribeMessage('message') handleTestMessage( @MessageBody() message: string, @ConnectedSocket() client: Socket, ) { const username = client.handshake.query.name[0]; const sendMessage = `${username} : ${message}`; this.io.emit('message', sendMessage); } }
TypeScript
복사