WebSocket

ws

프로젝트에 사용할 ws라이브러리 이용법에 대해

Installation

먼저 필요한 패키지들을 설치한다.

$ pnpm install @nestjs/websockets @nestjs/platform-ws ws

nest에서 ws이용법

nestjs에서 WebSocket은 socket.io가 기본으로 되어있어 ws를 사용하려면 main.ts 에서 설정을 해줘야한다.(테스트에서도)

app.useWebSocketAdapter(new WsAdapter(app));

RestApi에서는 controller가 있지만 ws에서는 gateway파일이 있다. 둘다 클라이언트에서 오는 요청을 처리하는 곳이다.

gateway파일에서 각종 응답처리 로직을 작성하면 된다.

데코레이터 등은 추후 추가 예정

//클라이언트
const ws = new WebSocket('ws://localhost:3000/chat');
        const messages = document.getElementById('messages');

        ws.onopen = () => {
            console.log('연결됨');
            addMessage('시스템', '서버에 연결되었습니다.');
        };

        ws.onmessage = (event) => {
            const data = JSON.parse(event.data);
            
            switch(data.event) {
                case 'response':
                    addMessage('서버', data.data);
                    break;
                
                case 'broadcast':
                    addMessage(data.data.sender, data.data.message);
                    break;
                
                case 'serverTime':
                    addMessage('서버시간', data.data.time);
                    break;
            }
        };

        ws.onclose = () => {
            addMessage('시스템', '서버와 연결이 끊어졌습니다.');
        };

        function sendMessage() {
            const nameInput = document.getElementById('nameInput');
            const messageInput = document.getElementById('messageInput');
            
            if (messageInput.value) {
                ws.send(JSON.stringify({
                    event: 'chat',
                    data: {
                        sender: nameInput.value || '익명',
                        message: messageInput.value
                    }
                }));
                messageInput.value = '';
            }
        }

        function addMessage(sender, message) {
            const li = document.createElement('li');
            li.textContent = `${sender}: ${message}`;
            messages.appendChild(li);
            messages.scrollTop = messages.scrollHeight;
        }

클라이언트와 서버에서 각각 요청 보내고 받기(ai생성 예제)

//서버
interface ChatMessage {
  sender: string;
  message: string;
}

@WebSocketGateway({
  path: '/chat'
})
export class ChatGateway {
  @WebSocketServer()
  server: Server;

  // 클라이언트로부터 메시지 수신
  @SubscribeMessage('chat')
  handleChat(client: WebSocket, message: ChatMessage): void {
    console.log(`메시지 수신: ${message.sender}: ${message.message}`);
    
    // 클라이언트에게 응답
    client.send(JSON.stringify({
      event: 'response',
      data: `서버 응답: "${message.message}" 메시지를 받았습니다.`
    }));

    // 모든 클라이언트에게 브로드캐스트
    this.broadcast({
      event: 'broadcast',
      data: {
        sender: message.sender,
        message: message.message,
        time: new Date().toISOString()
      }
    });
  }

  // 서버에서 주기적으로 메시지 전송 (예: 5초마다)
  onModuleInit() {
    setInterval(() => {
      this.broadcast({
        event: 'serverTime',
        data: {
          time: new Date().toISOString()
        }
      });
    }, 5000);
  }

  // 모든 클라이언트에게 메시지 브로드캐스트
  private broadcast(message: any): void {
    const messageStr = JSON.stringify(message);
    this.server.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(messageStr);
      }
    });
  }
}