개발 일지

socket.io 서버 소켓에서 연결된 클라이언트 소켓 ID와 입장한 room을 찾는 방법

jayoon 2024. 8. 2. 16:14

개요

채팅을 구현하는 것은 이번이 두 번째입니다. 처음 구현할 때는 웹 개발을 처음했을 때라 웹소켓보다 기본적인 API에 집중했습니다. 그러다 보니 소켓 관련 부분은 게임 파트 동료가 만들어둔 것을 사용하는 형식으로 했고, 디테일이 부족했습니다. 하지만 이번에 채팅을 한 번 더 구현할 기회가 생겨 관련하여 공부하고, 기록으로 남겨볼 예정입니다.

 

본문

현재 ec2 docker의 WAS의 아키텍처는 무중단 배포를 위해 인스턴스가 두 개 존재합니다. 때문에 클라이언트와의 통신 요청-응답 사이에 상태를 서버에서 저장하면 안 됩니다. DB 등의 또다른 인스턴스에서 저장해야 한다는 이야기이죠. 때문에 In-memory caching을 할 수 있는 Redis 등을 이용하여 서버 소켓을 저장해야 합니다. 이렇게 redis adapter를 이용하여 서버 소켓 객체를 받으면 어느 서버 인스턴스든지 이를 통해 연결된 클라이언트 소켓의 ID와 존재하는 방을 알 수 있습니다.

room

      console.log('rooms', serverSocket.sockets.adapter.rooms)
      
      // output
      rooms Map(4) {
          'hpHrhLuOFNPuAAAC' => Set(1) { 'hpHrhLuOFNPuAAAC' },
          '1' => Set(3) {
            'hpHrhLuOFNPuAAAC',
            'Kt0IeYreQTXIAAAE',
            '7d2iS0GAzF5kAAAH'
          },
          'Kt0IeYreQTXIAAAE' => Set(1) { 'Kt0IeYreQTXIAAAE' },
          '7d2iS0GAzF5kAAAH' => Set(1) { '7d2iS0GAzF5kAAAH' }
        }

rooms는 위와 같이 serverSocket.sockets.adapter.rooms에 존재하는 방과 해당 방에 들어가 있는 클라이언트 목록을 볼 수 있습니다. 현재 '1'이라는 방과 그 방 안에 있는 클라이언트 세 명이 존재하죠. 클라이언트는 기본적으로 자신의 소켓 id를 방으로 가지게 됩니다. 때문에 하나의 방만 존재함에도 rooms 객체에는 네 개의 방이 있습니다. 때문에 방만 필터하고 싶다면 소켓 id를 제외하고 가져와야 합니다.

클라이언트 소켓 ID

소켓 id는 serverSocket.sockets.adapter.sids에서 얻을 수 있습니다. sids는 아래와 같습니다.

console.log('sids', serverSocket.sockets.adapter.sids)

// output
sids Map(3) {
  '7Uy5Jqn_SufcAAAK' => Set(2) { '7Uy5Jqn_SufcAAAK', '1' },
  'EAQ1XXIx-xuVAAAN' => Set(2) { 'EAQ1XXIx-xuVAAAN', '1' },
  'Mya1TbP-4qoAAAAQ' => Set(4) { 'Mya1TbP-4qoAAAAQ', '1', '2', '3' }
}

sids 객체는 Map<key, value>으로 자신의 소켓 id를 key로 하고, 자신이 입장해 있는 방의 id를 set으로 value를 갖고 있습니다. 클라이언트는 모두 자기의 소켓 id로 된 방에 들어가 있습니다. 세 번째 클라이언트만 추가로 두 개의 방에 더 들어간 모습입니다.