프레임워크/Nest.js

Nest.js 웹소켓 (WebSockets) 이란? + 사용법

Jake Seo 2024. 2. 11. 13:46

웹소켓 게이트웨이

  • 웹소켓 게이트웨이란, 웹소켓에서 REST Controller 와 비슷한 역할을 해주는 것이라고 보면 된다.
    • 단, 진입점이 단순히 엔드포인트가 아니라 이벤트(namespace)이며, 뒤에 추가 path 가 있는 게 아니라 추가 event 가 더 있는 것으로 보면 된다.
    • 웹소켓에서 엔드포인트는 단순히 처음 connection 을 맺을 때 한번만 쓰인다.
  • @WebSocketGateway() 데코레이터를 단 클래스이다.
  • 게이트웨이는 플랫폼에 구애받지 않으므로 어댑터가 생성되면 모든 WebSockets 라이브러리와 호환된다.

picture 0

의존성 설치

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

기본 사용법

  • 기본으로 HTTP 와 동일하게 80 포트를 사용하고, 게이트웨이에 사용될 네임스페이스를 지정할 수 있다.
  • 게이트웨이는 기존 모듈에서 참조되기 전까지는 인스턴스화되지 않는다.
@WebSocketGateway(80, { namespace: 'events' })
  • 2번째 인자엔 네임스페이스 뿐만 아니라 다양한 옵션을 지원한다.
@WebSocketGateway(81, { transports: ['websocket'] })
  • 실제로 특정 메세지를 구독하는 예시이다.
  • @SubscribeMessage@MessageBody 모두 @nestjs/websockets 패키지에 존재한다.
// events.gateway.ts
@SubscribeMessage('events')
handleEvent(@MessageBody() data: string): string {
  return data;
}

모듈에 게이트웨이 등록 방법

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

데코레이터 사용하지 않기

  • 데코레이터는 사용하지 않지만, 같은 결과를 만들 수 있다.
  • 그러나 데코레이터를 사용하지 않으면, 소켓 인스턴스를 모킹해야 하기 때문에 테스트에서 좋지 않다.
  • 연결된 소켓 인스턴스에 접근하려면 @ConnectedSocket() 데코레이터를 사용할 수 있다.
@SubscribeMessage('events')
handleEvent(@MessageBody('id') id: number): number {
  // id === messageBody.id
  return id;
}
@SubscribeMessage('events')
handleEvent(client: Socket, data: string): string {
  return data;
}

비동기 응답

  • async 키워드 혹은 Observable 을 활용해 비동기 응답이 가능하다.
@SubscribeMessage('events')
onEvent(@MessageBody() data: unknown): Observable<WsResponse<number>> {
  const event = 'events';
  const response = [1, 2, 3];

  return from(response).pipe(
    map(data => ({ event, data })),
  );
}

라이프사이클 훅

  • OnGatewayInit: afterInit() 메서드를 강제로 구현. 라이브러리별 서버 인스턴스를 인수로 받는다. (필요하다면 스프레드)
  • OnGatewayConnection: handleConnection() 메서드를 강제로 구현. 라이브러리에 특화된 클라이언트 소켓 인스턴스를 인수로 받는다.
  • OnGatewayDisconnect: handleDisconnect() 메서드를 강제로 구현. 라이브러리에 특화된 클라이언트 소켓 인스턴스를 인수로 받는다.

Broadcasting

  • 나를 제외한 모두에게 메세지를 보내는 것을 Broadcasting 이라고 한다.
socket.to("room 이름").emit("receive_message", "메세지");
반응형