상세 컨텐츠

본문 제목

[TIL] 2024.04.23 nest 기본 socket 구성

[TIL]

by 재호링 2024. 4. 24. 13:44

본문

설치 

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

개요 

@WebSocketGateway(80)데코레이터 에 인수를 전달하여 수정할 수 있습니다 . 다음 구성을 사용하여 게이트웨이에서 사용하는 네임스페이스를설정

@WebSocketGateway(80, { namespace: 'events' })

아래와 같이 데코레이터 에 대한 두 번째 인수를 사용하여 지원되는 옵션을 소켓 생성자에 전달 .@WebSocketGateway()

@WebSocketGateway(81, { transports: ['websocket'] })

이제 게이트웨이가 수신 중이지만 수신 메시지를 아직 구독하지 않았습니다. 메시지를 구독 events하고 정확히 동일한 데이터로 사용자에게 응답하는 핸들러를 만들어 보겠습니다.

@SubscribeMessage('events')
handleEvent(@MessageBody() data: string): string {
  return data;
}
힌트@SubscribeMessage()데코레이터 는 패키지 @MessageBody()에서 가져옵니다 @nestjs/websockets.

게이트웨이가 생성되면 모듈에 등록할 수 있습니다.

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

속성 키를 데코레이터에 전달하여 수신 메시지 본문에서 추출할 수도 있습니다.

@SubscribeMessage('events')
handleEvent(@MessageBody('id') id: number): number {
  // id === messageBody.id
  return id;
}
 
@SubscribeMessage('events')
handleEvent(client: Socket, data: string): string {
  return data;
}

위의 예에서 handleEvent()함수는 두 개의 인수를 사용합니다. 첫 번째는 플랫폼별 소켓 인스턴스 이고 , 두 번째는 클라이언트로부터 수신된 데이터입니다. 하지만 이 접근 방식은 socket각 단위 테스트에서 인스턴스를 모의해야 하기 때문에 권장되지 않습니다 .

메시지가 수신 되면 events핸들러는 네트워크를 통해 전송된 것과 동일한 데이터가 포함된 승인을 보냅니다. 또한 메소드를 사용하는 등 라이브러리별 접근 방식을 사용하여 메시지를 내보낼 수도 있습니다 client.emit(). 연결된 소켓 인스턴스에 액세스하려면 @ConnectedSocket()데코레이터를 사용하십시오.

@SubscribeMessage('events')
handleEvent(
  @MessageBody() data: string,
  @ConnectedSocket() client: Socket,
): string {
  return data;
}

그러나 이 경우 인터셉터를 활용할 수 없습니다. 사용자에게 응답하지 않으려면 해당 return명령문을 건너뛰면 됩니다(또는 명시적으로 "거짓" 값을 반환합니다(예 undefined: ).

이제 클라이언트가 다음과 같이 메시지를 내보내면:

socket.emit('events', { name: 'Nest' });

메서드 handleEvent()가 실행됩니다. 위 핸들러 내에서 방출된 메시지를 수신하려면 클라이언트는 해당 승인 리스너를 연결해야 합니다.

socket.emit('events', { name: 'Nest' }, (data) => console.log(data));

다중 응답 

승인은 한 번만 전달됩니다. 또한 기본 WebSocket 구현에서는 지원되지 않습니다. 이 제한을 해결하기 위해 두 가지 속성으로 구성된 객체를 반환할 수 있습니다. 는 event생성된 이벤트의 이름이며 data클라이언트에 전달되어야 합니다.

@SubscribeMessage('events')
handleEvent(@MessageBody() data: unknown): WsResponse<unknown> {
  const event = 'events';
  return { event, data };
}

들어오는 응답을 수신하려면 클라이언트가 다른 이벤트 리스너를 적용해야 합니다.

socket.on('events', (data) => console.log(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 })),
  );
}

위의 예에서 메시지 핸들러는 (배열의 각 항목에 대해) 3번 응답합니다.

수명주기 후크 

3가지 유용한 수명 주기 후크를 사용할 수 있습니다. 이들 모두에는 해당 인터페이스가 있으며 다음 표에 설명되어 있습니다.

OnGatewayInit 메서드 를 구현하도록 강제합니다 afterInit(). 라이브러리별 서버 인스턴스를 인수로 사용하고 필요한 경우 나머지를 분산시킵니다.
OnGatewayConnection 메서드 를 구현하도록 강제합니다 handleConnection(). 라이브러리별 클라이언트 소켓 인스턴스를 인수로 사용합니다.
OnGatewayDisconnect 메서드 를 구현하도록 강제합니다 handleDisconnect(). 라이브러리별 클라이언트 소켓 인스턴스를 인수로 사용합니다.

 

서버

때로는 기본 플랫폼별 서버 인스턴스 에 직접 액세스하고 싶을 수도 있습니다 . 이 개체에 대한 참조는 afterInit()메서드( 인터페이스) 에 인수로 전달됩니다 OnGatewayInit. 또 다른 옵션은 데코레이터를 사용하는 것입니다 @WebSocketServer().

@WebSocketServer()
server: Server;

 

관련글 더보기