nest에서 웹소켓은 기본적으로 socket.io를 활용함

따라서 ws를 사용하기 위해서는 @nestjs/platform-ws의 웹소켓 아답터를 별도로 등록해야함

const app = await NestFactory.create(ApplicationModule);
app.useWebSocketAdapter(new WsAdapter(app));

app.useWebSocketAdapter()는 NestJS에서 WebSocket 애플리케이션을 설정할 때 사용하는 메서드입니다. 이 메서드는 애플리케이션의 기본 WebSocket 동작 방식을 사용자 정의하기 위해 WebSocket 어댑터를 등록하는 데 사용됩니다. NestJS는 WebSocket 프로토콜을 추상화하기 위해 어댑터 패턴을 활용하며, 개발자는 이 메서드를 사용하여 기본 어댑터 대신 자신만의 어댑터를 지정할 수 있습니다.

기본 동작 원리

  1. WebSocket 어댑터 역할

    WebSocket 어댑터는 WebSocket 서버를 생성하고 클라이언트와 통신을 관리하는 책임을 집니다.

    예를 들어:

  2. 기본 어댑터

    NestJS는 기본적으로 @nestjs/platform-socket.io 모듈의 Socket.IO 어댑터를 사용합니다. 그러나, WebSocket의 기본 라이브러리(ws), 다른 프로토콜, 또는 커스텀 로직을 사용하려는 경우 사용자 정의 어댑터를 제공해야 합니다.

app.useWebSocketAdapter() 동작 과정

  1. 애플리케이션이 시작되면 WebSocket 어댑터가 초기화됩니다.
  2. 등록된 어댑터가 WebSocket 서버의 설정과 동작을 제어합니다.
  3. 개발자는 어댑터 내부에서 WebSocket 서버를 구성하고 이벤트 처리를 세부적으로 제어할 수 있습니다.

WebSocketAdapter 인터페이스

/**
 * @publicApi
 */
export interface WebSocketAdapter<
  TServer = any,
  TClient = any,
  TOptions = any,
> {
  create(port: number, options?: TOptions): TServer;
  bindClientConnect(server: TServer, callback: Function): any;
  bindClientDisconnect?(client: TClient, callback: Function): any;
  bindMessageHandlers(
    client: TClient,
    handlers: WsMessageHandler[],
    transform: (data: any) => Observable<any>,
  ): any;
  close(server: TServer): any;
}

NestApplication

/**
 * @publicApi
 */
export class NestApplication
  extends NestApplicationContext<NestApplicationOptions>
  implements INestApplication
{
  protected readonly logger = new Logger(NestApplication.name, {
    timestamp: true,
  });
  private readonly middlewareModule: MiddlewareModule;
  private readonly middlewareContainer = new MiddlewareContainer(
    this.container,
  );
  private readonly microservicesModule =
    MicroservicesModule && new MicroservicesModule();
    
  // 
  **private readonly socketModule = SocketModule && new SocketModule();**
  
  
  private readonly routesResolver: Resolver;
  private readonly microservices: any[] = [];
  private httpServer: any;
  private isListening = false;

  constructor(
    container: NestContainer,
    private readonly httpAdapter: HttpServer,
    private readonly config: ApplicationConfig,
    private readonly graphInspector: GraphInspector,
    appOptions: NestApplicationOptions = {},
  ) {
    super(container, appOptions);

    this.selectContextModule();
    this.registerHttpServer();
    this.injector = new Injector({ preview: this.appOptions.preview });
    this.middlewareModule = new MiddlewareModule();
    this.routesResolver = new RoutesResolver(
      this.container,
      this.config,
      this.injector,
      this.graphInspector,
    );
  }
  // 이후 생략
}

useWebSocketAdapter는 config에 웹소켓 아답터(ioAdapter)를 설정함

public useWebSocketAdapter(adapter: WebSocketAdapter): this {
    this.config.setIoAdapter(adapter);
    return this;
  }