2025-12-03

오늘 배운 것

  • 실시간 메시징 어떻게 구현
    • 개념
      • 서버와 클라이언트가 양방향으로 즉시 데이터 교환이 가능한 시스템
      • 메시지를 보내면 거의 실시간에 가깝게 상대방에게 전달되는 구조
    • 기본 구조

        [ 클라이언트 ]
                
        (1) 실시간 통신 계층 (WebSocket )
                
        (2) 메시징 서버
                
        (3) 메시지 브로커 (Pub/Sub)
                
        (4) 저장소(DB, 캐시)
      
    • 실시간 통신 방식
      • WebSocket
        • TCP 기반 양방향 통신
        • 클라이언트 ↔ 서버 둘 다 자유롭게 메시지 보냄
        • 끊기지 않는 장기 연결
        • 실시간 채팅 기본
      • SSE(Server-Sent Events)
        • 서버 → 클라이언트 단방향 스트림
        • 실시간 알림(주가, 뉴스)에 주로 사용
      • Long Polling
        • HTTP 요청을 오래 유지해서 서버가 응답 가능할 때까지 기다리는 방식
        • WebSocket이 불가능한 환경의 fallback
          • fallback : 원래 방식이 안될 때 대체로 사용하는 방식
    • 메시징 서버
      • 클라이언트와 WebSocket을 직접 연결하는 서버
      • 역할
        • WebSocket 핸드 셰이크 처리
        • 유저 인증(JWT 등)
        • 연결 관리 (userId ↔ connectionId)
        • 메시지 수신 및 검증
        • 메시지를 브로커로 publish (보내기)
        • 브로커로부터 메시지를 subscribe (받기)
        • 다시 클라이언트로 push
      • 특징
        • Stateless(무상태)로 설계해야 확장 쉬움 → 상태는 모두 Redis나 브로커로 위임
    • 메시지 브로커 / Pub-Sub 시스템
      • Pub/Sub (Publish-Subscribe)
        • Producer가 토픽에 메시지를 publish하면, 그 토픽을 subscribe한 Consumer들에게 메시지가 전달되는 구조
      • 대표 브로커 기술
        • Redis Pub/Sub
          • 가벼움, 빠름
          • 순서보장이 약함
          • 메시지 유실 가능
          • 소규모 채팅/알림 사용
        • Redis Streams
          • 소비 그룹, offset 관리됨
          • 메시지 유실 방지
          • Kafka와 유사한 구조의 경량 버전
        • Kafka
          • 파티션 단위로 강력한 순서 보장
          • 메시지 유실 방지
          • 대규모 서비스에서 가장 많이 사용
        • RabbitMQ
          • 라우팅, 지연 메시지 등 기능 풍부
          • 실시간 메시지보다 업무 로직 큐에 자주 사용
      • RabbitMQ vs Kafka
        • RabbitMQ
          • 메시지 큐 기반
          • 라우팅, 지연메시지, 우선순위 등 기능 풍부
          • 메시지를 업무 로직 처리용으로 보내는데 강함
          • 실시간 채팅용으로는 덜 적함(순서보장 약함)
          • 예 : 주문 처리 큐, 이메일 전송 큐, 백그라운드 작업
        • Kafka
          • 분산로그 + Pub/Sub 기반
          • 압도적인 처리량
          • 파티션 단위 순서보장 강함
          • 메시지를 장기간 보관 가능
          • 실시간 스트림 처리/채팅에 최적
          • 예 : 채팅 메시징, 실시간 로그 수집, 대규모 이벤트 스트리밍, MSA 이벤트 브로커
    • 방 개념과 라우팅
      • 실시간 메시징의 90%는 방 단위 라우팅
        • room-123에 메시지가 발행되면 → room-123에 있는 유저들만 메시지 받음
      • 구현
        • 유저가 로그인하면 참여 방 목록 저장
        • 메시지 publish 시 roomId 같이 전달
        • 브로커가 roomId에 필요한 서버 인스턴스들에게 전달
        • 해당 서버가 클라이언트에게 push
    • 확장성 문제와 해결 방식
      • 실시간 메시징은 서버 1대로는 절대 못 함
      • 해결방식
        • 메시징 서버 수평 확장(스케일 아웃)
          • 여러 서버가 웹소켓 연결을 분담
          • 상태는 레디스 또는 브로커에 저장해 공유
        • 방 단위 샤딩
          • 룸 아이디를 기반으로 shard = roomId % 서버 개수
          • 이런 식으로 특정 서버가 특정 방을 담당하게 할 수도 있음
        • 브로커 기반 확장
          • 카프카 파티션 개수를 늘리면 메시지 처리량을 늘릴 수 있음
            • 카프카 파티션 : 토픽을 여러 개의 조각으로 나눈 것
              • 각 파티션은 독립적으로 메시지를 순서대로 저장
              • 파티션 개수가 많을수록 병렬 처리량 증가
    • 메시지 순서 보장
      • 순서 보장이 필요한 이유
        • 같은 채팅방에서 메시지 순서 뒤죽박죽이면 사용자 경험 망가짐
      • 대표 방식
        • 카프카 파티션 기반 순서 보장
          • 방단위로 하나의 파티션만 사용 → FIFO
        • 샤딩 기반으로 한 서버가 해당 방 메시지 모두 처리하게 하는 방식
    • 메시지 중복 처리
      • 메시지를 재전송하면 중복이 발생할 수 있음
      • 메시지마다 유니크 아이디 부여
      • 클라이언트는 이미 처리한 메시지 아이디면 무시
    • 유실방지
      • 대표 전달 방식
        • at-most-once
          • 중복 없음
          • 유실 가능
        • at-least-once
          • 재전송 포함
          • 중복 발생 가능 → 멱등성 필요
        • exactly-once
          • 실질적으로 구현하기 어려움
          • 큰 시스템은 대부분 at-least-once 기반
    • 오프라인 메시지 처리
      • 유저가 오프라인일 경우
        • 메시지를 DB에 저장
        • 모바일 Push(FCM/APNS) 전송
          • FCM(Firebase Cloud Messaging)
            • 구글이 제공하는 모바일 푸시 알림 서비스
            • 안드로이드 기본
            • iOS도 지원하지만 APNS를 내부적으로 사용
            • 오프라인인 사용자를 깨울 때 사용
          • APNS(Apple Push Notification Service)
            • 애플이 제공하는 iOS Push 알림 서비스
            • iPhone은 FCM을 직접 쓰는게 아니라 FCM → 내부적으로 APNS로 메시지를 다시 보내서 전달
        • 유저 재접속 시 → 마지막 읽은 메시지 아이디 이후 메시지 재전송
    • Presence & 상태 동기화 (온라인/오프라인 표시)
      • Redis에 userId → online/offline + serverId 저장
      • 상태 변경 시 브로커로 이벤트 발행
      • 친구 목록/방 유저 목록 업데이트
    • 저장소
      • 메시지 로그 저장
        • RDB : MySQL, PostgreSQL
        • NoSQL: Cassandra, DynamoDB
        • 검색: ElasticSearch
      • 읽음 처리, 최근 N개 로딩 최적화 등을 위해 레디스 캐시 사용
    • 장애 복구
      • 서버 장애 발생 시
        • 웹소켓 끊김 → 클라이언트 자동 재연결
        • 재연결 시 미처 못받은 메시지를 DB에서 fetch
        • Stateless 서버라서 다른 인스턴스가 연결 처리 가능
    • 인증/보안
      • 웹소켓 업그레이드 시 JWT 검사
      • TLS 사용
      • 방 참여 권한 체크(ACL)
        • ACL(Access Control List) : 누가 어떤 리소스에 접근 가능한지 정의한 권한 목록
      • Rate Limit 적용(스팸 방지)
        • 너무 많은 요청을 보내는 클라이언트 제한하는 기술
          • 초당 메시지 전송 개수 제한
          • IP당 초당 요청 개수 제한
          • API 호출 제한
        • 방법
          • 토큰 버킷 알고리즘
          • leaky bucket
          • Redis 기반 rate limiting
    • 운영/모니터링
      • 프로메테우스 : 연결 수, 초당 메시지 수, 지연(단락) 측정
      • 그라파나 : 시각화
      • 로그: ELK Stack
        • ELK (Elasticsearch Logstash Kibana)
          • 로그 수집/저장/검색/시각화 통합 도구 세트
      • 알림: Slack/Discord/Webhook

results matching ""

    No results matching ""