개발자 삽살개

멀티 채팅 만들기 (소켓 프로그래밍) 본문

개발하다가

멀티 채팅 만들기 (소켓 프로그래밍)

개발자 삽살개

전에 자바와 Node.js로 멀티채팅을 만들었다.
대강 이렇겠지라고 생각했는데, 막상 표현을 하려니 기억이 안나더라.
다시 내가 짰던 코드를 열고 어떻게 만들었는지 확인해보았다.

오랜만에 보니 내가 했던 고민들이 생각났다.
첫 소켓프로그래밍은 자바로 시작했었다.
소켓통신이 이해가 안되서 5일간 구글링이랑 유튜브를 봤던 기억이 났다 ㅋㅋ
이해하기 위해 테스트코드를 짰었는데, 소스코드가 남아있었다.

ver 1. [테스트코드] 자바 소켓프로그래밍

 

[서버]
1. 서버에서 프로그램이 실행됨
2. 프로그램이 실행되면, 서버소켓을 생성.
3. 서버소켓이 생성되면, 클라이언트 접속을 기다림
4. 클라이언트하면, 클라이언트의 정보를 알고 있는 소켓을 생성한다.
5. 소켓 정보를 갖고 있는 유저 쓰레드을 생성해 줌. 그리고 쓰레드를 유저리스트에 저장함.
(각 쓰레드는 해당 유저가 보내는 데이터를 감지하고, 참여자들에게 데이터를 보내는 일을 한다.)

6. 클라이언트의 접속이 끊어지면, 클라이언트 쓰레드를 종료시키고 리스트에서 제거한다.


[클라이언트]
1.유저는 ip와 포트번호를 가지고 서버에 접속을 시도한다.
2. 서버에 연결이 되면 소켓이 생성된다.
3. 소켓을 이용해서 인풋스트림, 아웃풋스트림 객체를 생성한다.
4. 아웃풋스트림으로 데이터를 보내고, 인풋스트림으로 데이터를 받도록 한다.


완성 후, 채팅을 해보면 한공간에 참여자들이 모여있는 것처럼 보인다.


ver2. 방 나누기. [클라이언트에서 처리]


참여자들이 소통은 가능하지만, 모든 사람과는 대화하고 싶지 않을 것이다.

그래서 방을 나눠주기로 했다.

위에서 따로 처리를 하지 않고, 대화를 처리하면 다음과 같은 현상이 발생한다.
1. A가 채팅을 침.
 2. 모든사람에게 A의 채팅이 보임.

그러면 A가 친 채팅이 방에 참가하지 않은사람만 안보이면 되는거잖아? 라는 생각으로 접근했다.

1. 클라이언트가 메시지를 보낼때, 아웃풋스트림 텍스트를 방번호와 함께 보내게 했다.
2. 모든 사람이 메시지를 받음.
3. 메시지를 파싱
4. 방 참가자 여부를 확인한 후 텍스트를 보이게 ,안보이게 처리
(해당 방 참가자가 아니면, 텍스트가 보이지 않음)

작동은 잘 했다 ㅋㅋㅋㅋㅋ
하지만 모든사람에게 메시지를 보내는 것은 분명 잘못된 방법이었다.

정말 생각이 없었다. 이렇게 처리할 생각을 하다니..
이 일이 있고나서는 고민하고 만들고 있다.

 

ver 3. 서버에서 방나누기

 

위에서 만든 것이 이런 구조였다면,

 

 

 

위와 같이 방을 확실하게 나누는 구조로 변경했다.



방법은 간단했다.
서버에서 방목록 관리하면 되는 것이였다.
그래서 서버에 방목록 리스트를 추가했다.
클라이언트가 접속 시, 유저가 참여하고 있는 방마다 유저를 넣어주었다.

  • sids:Map<SocketId, Set<Room>>
  • rooms:Map<Room, Set<SocketId>>

클라이언트가 메시지를 보낼때는 자신의 채팅과 함께 방이름을 보내게 했다.
서버에 메시지가 도착하면 해당 방 이름을 가진 참가자에게만 전송했다. 

 

자바가 아니라...
node.js의 socket.io 라이브러리를 사용하면 정말 쉽게 멀티채팅 기능 구현이 가능하다.

socket.io에는 특정룸에 메시지를 보내는 메서드가 있기 때문이다.
io.to("room2").emit("details", details);
위와 같이 to()에 방 이름을, emit에 메시지를 보내면 된다.

그러면 자바에서 쓰레드를 사용하고, 방을 어떻게 나눌까, 어떻게 메시지를 보낼까 했던 고민들이 싹 사라진다.

https://socket.io/docs/v3/rooms/

 

Rooms | Socket.IO

A room is an arbitrary channel that sockets can join and leave. It can be used to broadcast events to a subset of clients:

socket.io


나중에 webrtc도 도전해봐야겠다.

돌이켜보면, 안드로이드는 생명주기가 있어서 어느시점에 클라이언트가 접속을 하고, 어느시점에 끊어지게 해야하는지도 고민이었다.는 생각이 든다.

Comments