저장을 습관화

NestJS - socket.broadcast.emit() 브로드캐스팅 방식 본문

공부/node.js

NestJS - socket.broadcast.emit() 브로드캐스팅 방식

ctrs 2023. 10. 20. 20:14

일반적으로 소켓 통신은, 동일한 소켓 아이디를 가진 서버와 클라이언트 간의 일대일통신이다.(유니캐스트)

 

현재 서버와 연결 중인 모든 소켓을 대상으로 통신을 보내고 싶을때(브로드캐스트)는

socket.broadcast.emit()을 사용한다.

 

준비

- index.hbs

<html>
  <head>
	{{! 중략 }}
  </head>

  <body>
    <div id='hello_stranger'></div>
    <div id='chatting_box'></div>
    <form id='chat_form'>
      <input placeholder='Chat...' />
      <button type='submit'>Chat</button>
    </form>

    {{! 중략 }}
    
    {{! socket.io - 웹 클라이언트와 서버 간 실시간 양방향 통신을 지원해줌}}
    <script
      src='https://cdn.socket.io/3.1.3/socket.io.min.js'
      integrity='sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh'
      crossorigin='anonymous'
    ></script>

    <script src='js/scripts.js'></script>
  </body>
</html>

 

- script.js

const socket = io('/chattings');

const getElementById = (id) => {
  return document.getElementById(id) || null;
};

// get DOM element
const helloStrangerElement = getElementById('hello_stranger');

// 신규 사용자 연결 알림
socket.on('user_connected', (username) => {
  console.log(`${username} connected!`);
});

// 접속한 사용자의 이름을 웹 페이지에 띄워주는 함수
const drawHelloStranger = (username) => {
  helloStrangerElement.innerText = `Hello ${username} Stranger :)`;
};

// 접속한 사용자의 이름을 묻는 프롬프트를 띄우는 함수
const helloUser = () => {
  const username = prompt('What is your name?');
  socket.emit('new_user', username, (data) => {
    drawHelloStranger(data);
  });
};

const init = () => {
  helloUser();
};

init();

 

- chats.gateway.ts

import { Logger } from '@nestjs/common';
import {
  SubscribeMessage,
  WebSocketGateway,
  MessageBody,
  ConnectedSocket,
} from '@nestjs/websockets';
import { Socket } from 'socket.io';

@WebSocketGateway({ namespace: 'chattings' })
export class ChatsGateway /* 중략 */ {
  // 중략

  @SubscribeMessage('new_user')
  handleNewUser(
    @MessageBody() username: string,
    @ConnectedSocket() socket: Socket,
  ) {
    // 접속해 있는 모든 사용자에게 새로운 사용자의 username을 전달( broadcast)
    // 그냥 socket.emit을 사용하면 해당 소켓 아이디를 가진 대상에만 데이터를 보내지만,
    // broadcast를 사용하여 현재 서버와 연결 중인 모든 소켓에 데이터를 보낼 수 있다.
    socket.broadcast.emit('user_connected', username);
    return username;
  }
}

 

 

- 테스트

접속 및 사용자 이름 입력

 

크롬 시크릿 페이지를 사용하여 신규 사용자 사용자 B 접속

 

사용자 A의 웹 페이지의 콘솔 확인

'사용자 B connected!' 로그 확인

 

 

다른 브라우저 edge InPrivate을 이용하여 새로운 사용자 사용자 C 접속

 

사용자 A, 사용자 B의 콘솔 확인

사용자 A와 B의 브라우저에서 '사용자 C connected!' 로그 확인