본문으로 바로가기

Socket.IO Namespace, Room

category Node, Nest, Deno/⚡ ws , socket.io 2020. 4. 7. 21:32

socket.io/docs/v4/namespaces/

 

Namespaces

A Namespace is a communication channel that allows you to split the logic of your application over a single shared connection (also called “multiplexing”). IntroductionEach namespace has its own: ev

socket.io

각 view 단에서 socket 연결 부분을 가져와봤습니다. 메인 페이지에 들어가자마자 소켓이 보내주는 실시간 메세지를 모두 받을 필요는 없습니다. 불필요한 일이죠. 때문에 Socket.IO에서 "네임 스페이스"란 것을 활용합니다. 

 

말 그대로 이름이 붙은 공간이며 소켓을 묶어주는 단위라고 생각하셔도 됩니다.

 

 

네임스페이스 설정. io.of('/something')

 

socket 객체를 이용해 네임스페이스를 설정할 수 있습니다.

  // path 변수는 클라이언트가 /socket.io 경로 접근시 소켓 연결을 의미.
  const io = SocketIO(server, { path: '/socket.io' });

  // 네임 스페이스. 기본 네임스페이스는 io.of("/")입니다.
  app.set('io', io);
  const room = io.of('/room');
  const chat = io.of('/chat');

 

 

이제 네임스페이스를 생성한 다음 네임스페이스 별로 처리할 로직을 코드로 구현하면 됩니다.

 

그런데 아래 코드를 살펴보면 독특하게 join, to, leave 등 친숙한 동사, 전치사 메서드들이 보이는데 이는 socket.io에서 채팅방의 논리를 미리 구현해놓은 것입니다. join, leave의 개념은, socket.io의 Room 개념입니다. 네임스페이스의 하위 항목으로, socket에 참여할 수 있는 공간이라고 보면 됩니다.

 

사용하기 위해서 별도 작업 없이 그냥 생성하면 됩니다.

 

socket.io/docs/v4/rooms/

 

Rooms

A room is an arbitrary channel that sockets can join and leave. It can be used to broadcast events to a subset of clients: Please note that rooms are a server-only concept (i.e. the client does not h

socket.io

socket.join(roomId);
socket.to(roomId)
socket.leave(roomId);

 

위 코드를 전체 맥락에서 살펴보면 다음과 같습니다.

const SocketIO = require('socket.io');
const axios = require('axios');

module.exports = (server, app, sessionMiddleware) => {
  // path 변수는 클라이언트가 /socket.io 경로 접근시 소켓 연결을 의미.
  const io = SocketIO(server, { path: '/socket.io' });

  // 네임 스페이스. 기본 네임스페이스는 io.of("/")입니다.
  app.set('io', io);
  const room = io.of('/room');
  const chat = io.of('/chat');

  // io.use는 소켓에서 사용하는 미들웨어입니다. 다른 포스트에서 다룹니다
  io.use((socket, next) => {
    sessionMiddleware(socket.request, socket.request.res, next);
  });
  
  
  // =====================================
  // room 네임 스페이스에 접속시 처리할 것들.
  // =====================================
  room.on('connection', (socket) => {
    console.log('room 네임스페이스에 접속');
    
    socket.on('disconnect', () => {
      console.log('room 네임스페이스 접속 해제');
    });
  });
  
  
  
  // =====================================
  // chat 네임 스페이스에 접속시 처리할 것들.
  // =====================================
  chat.on('connection', (socket) => {
    console.log('chat 네임스페이스에 접속');
    const req = socket.request;
    
    // req에서 referer 빼낸 후 roomId로 정의
    const { headers: { referer } } = req;
    const roomId = referer
      .split('/')[referer.split('/').length - 1]
      .replace(/\?.+/, '');
    
    // socket.join (방 아이디) join은 socket.IO에서 만들어준 메소드임.
    socket.join(roomId);
    
    // socket.to(방 아이디).emit().
    // to와 emit은 socket.IO에서 만들어준 메소드임.
    socket.to(roomId).emit('join', {
      user: 'system',
      chat: `${req.session.color}님이 입장하셨습니다.`,
    });
    
    socket.on('disconnect', () => {
      console.log('chat 네임스페이스 접속 해제');
      // socket.leave(방 아이디) leav는 socket.IO에서 만들어준 메소드임.
      socket.leave(roomId);
      
      const currentRoom = socket.adapter.rooms[roomId];
      const userCount = currentRoom ? currentRoom.length : 0;
      
      if (userCount === 0) {
        axios.delete(`http://localhost:8005/room/${roomId}`)
          .then(() => {
            console.log('방 제거 요청 성공');
          })
          .catch((error) => {
            console.error(error);
          });
      } else {
        socket.to(roomId).emit('exit', {
          user: 'system',
          chat: `${req.session.color}님이 퇴장하셨습니다.`,
        });
      }
    });
  });
};

 

 

main.pug의 일부

//- 이하 소켓 관련 스크립트
script(src='/socket.io/socket.io.js')
script.

  // room 네임 스페이스와 연결합니다.
  var socket = io.connect('http://localhost:4000/room', {
    path: '/socket.io'
  });
  
  // newRoom이라는 키의 소켓 메세지에 반응합니다.
  socket.on('newRoom', function (data) {
    ... 중략
  });
  
  // removeRoom이라는 키의 소켓 메세지에 반응합니다.
  socket.on('removeRoom', function (data) {
    ... 중략
  });

 

chat.pug의 일부

script.
    // chat 네임 스페이스에 연결합니다.
    var socket = io.connect('http://localhost:3051/chat', {
      path: '/socket.io'
    });
    
    // join 키를 가진 소켓 메세지에 반응합니다.
    socket.on('join', function (data) {
      ... 중략
    });

 

 

 

 

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체