Home WebSocket + MessageQueue -> ChattingServer
Post
Cancel

WebSocket + MessageQueue -> ChattingServer

웹 소켓만을 사용한 채팅서버 아키텍쳐는?

IOS [SEND, msg : “반갑습니다 ^^”] -> Spring Boot (STOMP) -> Android [RECEIVE, msg : “반갑습니다 ^^”]

근데 이 아키텍쳐에서 IOS 가 보낸 메세지가 가진 목적지의 소켓을 어떻게 아는건가?

우선 메세지를 보내고자 하는 유저와 메세지를 수신할 유저의 유일하게 식별할 수 있는 어떤 값이 필요하다.

보편적으로 DB 도메인에 담겨있는 primary key 를 활용할 수 있을 것이다.

채팅을 보내고자 하는 것에는, 보내고자 하는 유저의 소켓은 이미 서버에 연결되어있음이 분명하다.

따라서 수신자의 소켓내용이 필요한데, 메세지의 수신자의 primary key 값을 넣은 후 그 값을 받아와 그 유저의 소켓 내용을 매핑하면 되는 것이다.

여기서 메세지 큐를 추가해보면 어떨까?

그 전에, 메세지 큐의 활용 목적은 무엇인가?

비동기 + 낮은 결합도

비동기는 무엇인가?

“나” 라는 사람이 5명에게 “Hi Yeom~” 이라는 메세지를 보내는 상황이라고 해보자.

동기방식

1
for (int i = 0; i < 5; i ++) send(user, message);

이렇게 처리가 될 것이다.

비동기방식

1
for (int i = 0; i < 5; i ++) asyncSend(user, message);

이것도 동기방식과 코드는 유사하다. 하지만 내부 처리 방식에 다른 점이 있다.

동기 방식은 User1 -> “User1 한테 보내졌습니둥~” -> User2 -> “User2한테 보내졌습니둥~” … 처럼 응답을 필요로 한다.

비동기 방식은 순차적으로 보내긴 하지만, 동기 방식과 달리 “User1한테 보내졌습니둥~” 이라는 응답자체를 받을 필요가 없기 때문에

User1 -> User2 -> … 이런 방식으로 진행되어

메세지 처리 하나당 1초가 걸린다고 했을 때 대략 동기 = 5초, 비동기 = 1.n초 가 소요된다.

그래서 비동기성을 가진 메세지 큐를 활용하면 어떻게 되는지?

  1. IOS 가 메세지를 나(서버)에게 보낸다.
  2. 나(서버)는 메세지 큐에 퍼블리싱한다.
  3. 나(리스너)는 큐에 쌓여있는 내용을 컨슘한다.

이렇게 하면, 확장이 매우 쉽게 된다는 장점이 있다. 이게 무슨 말이냐면

서버에서 Queue의 내용을 컨슘 할 수 있는 서버만 늘린다면 자연스럽게 큐의 내용을 처리하는 주체가 많아지게 되면서 확장이 이루어지는 것이다.

그래서 컨슘된 응답 메세지를 IOS 혹은 Android 에게 보내주면 채팅서버가 완료 되는 것이다.

만약 DB 에 저장하고 싶다면, 컨슘된 메세지를 DB에 저장하는 로직을 추가적으로 수행해주면 된다.

메세지 큐에 있는 값을 컨슘했을 때 고려해야할 점

IOS 가 보낸 메세지가 있고, 서버는 이 내용을 Queue 에서 컨슘하여 메세지를 보냈지만, 상대방은 채팅방에 입장하지 않은 상태이다.

그러면 어떻게 할 것인가?

이건 팀의 내부 정책에 따르면 된다. 큐에서 컨슘할 때 채팅방에 양측의 유저들이 존재한다면, 채팅을 보내주면 되는 것이고

그렇지 않다면 “노티” 를 통해 알림만 보내줄 수 있도록 조치해주는게 일반적이다.


WebSocket + MQ 흐름도

img.png

This post is licensed under CC BY 4.0 by the author.