Skip to content

Message Broker Introduction.md

Garyeong edited this page Sep 30, 2026 · 16 revisions

메시지 브로커 도입 근거

채팅 서버가 두 대이면 사용자 A와 B가 서로 다른 서버에 WebSocket으로 접속할 수 있다. A의 서버는 B의 연결을 직접 가지고 있지 않으므로 RDS에 메시지를 저장하는 것만으로는 B의 서버에 새 메시지를 즉시 알릴 수 없다.

메시지 저장을 확정한 서버가 방,메시지,수신자의 ID와 본문 이벤트를 발행하고 두 채팅 서버가 이를 구독한다. 각 서버는 자신의 로컬 WebSocket 연결에 수신자가 있는지 확인해 전달한다. 메시지 원본은 RDS에 둔다. 이벤트에 실린 본문은 정상 경로에서 즉시 전달하기 위한 전달용 복사본이고 원본은 항상 RDS에 있다.

sequenceDiagram
    autonumber
    participant A as 사용자 A
    participant S1 as 채팅 서버 1
    participant R as RDS
    participant V as Valkey Pub/Sub
    participant S2 as 채팅 서버 2
    participant B as 사용자 B

    A->>S1: 메시지 전송
    S1->>R: 메시지 저장 및 commit
    R-->>S1: 저장 완료
    S1->>V: 방 ID·메시지 ID·수신자 ID·본문 발행
    V-->>S1: 이벤트 전달
    V-->>S2: 이벤트 전달
    S1->>S1: 로컬 WebSocket 연결 확인
    S2->>S2: 로컬 WebSocket 연결 확인
    S2-->>B: 이벤트 본문 그대로 전달 (RDS 조회 없음)

    Note over V,S2: 구독이 끊기면 이벤트는 보관되지 않음
    S2->>V: 재구독
    S2->>R: 마지막 수신 메시지 이후 조회
    R-->>S2: 누락 메시지 반환
    S2-->>B: 누락 메시지 전달 (메시지 ID로 중복 제거)
Loading

메시지 전달 흐름

  1. 사용자 A가 채팅 서버 1로 메시지를 전송한다.
  2. 채팅 서버 1이 RDS에 메시지를 저장한다.
  3. 저장이 확정되면 채팅 서버 1이 Valkey Pub/Sub에방,메시지,수신자의 ID와 메세지 내용 이벤트를 발행한다.
  4. 두 채팅 서버가 이벤트를 수신하고 각자 자신의 로컬 WebSocket 연결을 확인한다.
  5. 수신자 B가 채팅 서버 2에 연결되어 있으면 채팅 서버 2가 이벤트에 실린 본문을 그대로 B에게 전달한다. 이때는 RDS를 다시 조회하지 않는다.

전달 정책

정상 상태에서는 온라인 알림을 즉시 전달한다. 다만 메세지 브로커의 구독이 끊긴 동안 이벤트를 보관하거나 재전송하지 않고 RDS를 조회해 한다.

  • 채팅서버와 메세지 브로커가 다시 연결되는 순간
  • 사용자 WebSocket이 재연결된 직후
  • 사용자가 채팅방을 다시 연 직후

각 조회는 사용자의 마지막 수신 메시지 ID 또는 방별 마지막 메시지 순번 이후를 기준으로 수행한다. 이미 전달된 메시지는 메시지 ID로 중복 제거한다. 메세지 브로커에 채팅의 본문을 담지 않는 이유는 채팅 메세지는 유실되면 안되는데 pub/sub은 구독이 없어지면 데이터가 버려지기 때문에 데이터 유실이 발생할 수 있어서 RDS에 저장합니다. Valkey Pub/Sub 전달 특성

본문을 이벤트에 싣는 이유

메시지 원본은 유실되면 안 되는 데이터이므로 RDS에 저장한다. 그 위에서 정상 전달 경로에는 본문을 이벤트에 함께 실어 RDS 재조회 없이 즉시 전달한다. 이벤트의 본문은 전달용 복사본이고 원본은 RDS에 있으므로 이벤트가 유실되어도 데이터는 보존될 수 있다. 메세지 브로커에서 메세지가 유실된 경우는 RDS 원본에서 내용을 가져온다. ID만 싣고 전달 때마다 RDS를 다시 읽으면 실시간 전달 경로에 메시지마다 RDS SELECT가 붙어 지연과 RDS 부하가 늘어날 수 있는데 메세지를 브로카에실으면 정상 경로에서 DB 읽기를 없앨 수 있다.

Clone this wiki locally