Skip to content

웹소켓 방 관리 구조 개선

Gyeongsu Choi edited this page Dec 1, 2024 · 8 revisions

초기 구현

기존에는 로비에서 방에 입장했을 때 같은 방에 있는 유저들만의 통신 채널을 만들어주기 위해 Socket.IO에서 제공하는 join 메서드를 사용했습니다. join 메서드는 아래와 같이 사용하며 같은 roomId에 속한 클라이언트끼리의 데이터 송수신이 가능하게 됩니다.

// client: socket.io.Socket
client.join(roomId);

문제점

하지만 join 메소드를 통해 방을 관리하는 방식은 아래와 같은 두 가지 단점이 있었습니다.

첫 번째로, join 메소드는 Socket.IO 라이브러리에서 제공해주는 특수한 기능이므로 다른 웹소켓 라이브러리를 사용하게 되면 사용하지 못하게 될 가능성이 높습니다.

두 번째로, 아래와 같은 방식으로 특정 방에 있는 클라이언트들에게 메시지를 전송할 수는 있지만 roomId로 클라이언트 소켓을 조회할 수는 없었습니다.

// server: socket.io.Server
server.to(roomId).emit('chat', 'message');

이로 인해 다른 모듈에서 방에 메시지를 전송하기 위해서는 서버 소켓 자체를 넘겨야하는 문제가 있었습니다.

그래서 client들을 같은 채널로 묶어서 관리하는 기능을 Socket.IO 라이브러리에 의존하지 않고 직접 구현하기로 했습니다.

개선된 구조

  • EventClient 클래스

내부에 Socket을 가지고 있으며 그 외에도 nickname 등의 정보를 추가로 가질 수 있습니다.

class EventClient {
  nickname: string;
  socket: socket.io.Socket;

  emit(event, ...args) {
    this.socket.emit(event, ...args);
  }
}
  • Room 클래스

위 EventClient의 배열을 관리하며 이를 이용해 방에 있는 클라이언트들에게 메시지 전송이 가능합니다.

class Room {
  roomId: string;
  clients: EventClient[];

  enter(client: EventClient) {
	  this.clients.push(client);
  }
  
  sendAll(event: string, ...args) {
    this.clients.forEach((c) => c.send(event, ...args));
  }
}

결과

이렇게 구조를 변경하니 다른 모듈에서 특정 방에 메시지를 전송할 필요가 있을 때 Room 객체 하나만 전달하면 되니 서버 소켓을 전달할 때 발생할 수 있는 문제를 예방할 수 있었습니다.

MafiaCamp

📔소개
🎯프로젝트 규칙
💻프로젝트 기획
🍀기술 스택
📚그룹 회고
🌈개발 일지
🍀문제 해결 경험
🔧트러블 슈팅
Clone this wiki locally