[쇼핑몰 프로젝트] 메시징 큐 도입 -1편

대원·2025년 1월 22일

쇼핑몰

목록 보기
8/13

메시징 큐 도입

배경

현재 진행 중인 토이프로젝트에 이전에 웹소켓을 이용해서 채팅을 구현하였습니다.

웹소켓이라는 건 HTTP와 같은 통신프로토콜이며 Http와 달리 양방향 통신이 가능하며 Connection을 끊지 않고 지속해서 유지하는 특성을 지니고 있습니다.

현재는 단일한 서버의 인스턴스만으로 실행하고 있지만, 트래픽이 몰려서 아래와 같이 Scale-Out된 상황을 가정해 봅시다.

유저 A(클라이언트)가 서버 인스턴스(1)와 웹소켓을 연결해서 채팅을 실행했다고 하자. 유저 A가 작성하는 채팅 내용은 서버 인스턴스(1)에는 기록이 되겠고 A는 실시간으로 확인이 가능할 것입니다.

유저 A와 대화를 하는 유저B는 서버 인스턴스(1)이 아니라 다른 서버 인스턴스(2)와 웹소켓을 연결해서 채팅을 한다고 하면 유저 A와 다른 서버의 인스턴스와 웹소켓이 연결되었기 때문에 A가 작성한 대화 내용을 확인할 수 없는 문제가 있습니다. 실시간 채팅 시스템의 서버 인스턴스 간의 상태 동기화가 이뤄지지 않는 심각한 문제는 사용자 경험을 크게 저하시킬 수 있습니다.

(트래픽을 가정하면) 사실상 실무 환경에서는 단일한 서버 인스턴스로 운영하는 것이 불가능하고 WAS를 스케일아웃하여 사용하기 때문에 이는 단순채팅 구현이 아닌 실무를 가정하면 아주 중요한 이슈사항이라고 할 수 있습니다.

이런 상황에서 아래와 같이 ‘메시징 큐’를 적절하게 도입하면 위와 같은 문제를 해결하는데 큰 도움이 될 수 있습니다.

메시지 큐

메시징 큐란 서버 인스턴스가 여러 대일때, 각 인스턴스 간 메시지 전달을 중개하는 일종의 중개 시스템으로서 위와 같은 채팅과 관련된 도메인뿐 아니라 여러 도메인에 걸쳐서 데이터를 중개자로서 비동기적 통신을 지원합니다.

대표적인 메시징 큐는 Kafka, Redis Pub/Sub 등이 존재합니다.

각 메시징 큐의 특성을 간단하게 알아보자면 다음과 같습니다.

메시징 큐

러프하게 이해하자면 큰 틀에서 메시징 큐의 기본 골조는 위의 그림과 같습니다.

네모 박스의 역할을 하는 것이 메시징큐(미들웨어)입니다.
좌측에 보이는 Publisher(Sender)와 우측에 보이는 Subscriber(Receiver)들이 각 인스턴스의 개념에 대응한다고 할 수 있습니다.

Publisher는 메시징큐 내부의 특정 Topic(또는 Channel)에 메시지를 전송하고 해당 Topic(또는 Channel)을 구독하는 Subscriber(Receiver)가 해당 메시지를 수신합니다.

큰 틀에서 메시징 큐가 하는 역할은 위와 같고 세부적으로 해당 메시지를 어떻게 처리하는지는 메시징 큐마다 제각각인데, 대표적 메시징 큐로는 Redis Pub/sub과 Kafka가 있습니다.

Redis Pub/sub

  • Redis의 특성인 인메모리 기반으로 빠른 성능을 제공한다.
    • 응답의 지연성이 낮다.
    • 메모리 내 데이터 저장소 이므로 기본적으로 휘발성이다.
      • 이에따라 Consumer가 메시지를 놓칠 수 있지만, Redis Streams 등으로 보완 가능하지만 구현 복잡도가 증가한다.
    • 메시지를 발행(Produce)하면 그 시점에 바로 구독(Consume)한다.
    • 일시적으로 네트워크가 끊긴 클라이언트는 ‘메시지’를 놓칠 수 있지만, 실시간 서비스에서는 크게 문제가 되지 않을 수 있지만, 도메인 특성에 따라 치명적 결점일 수 있다.
  • 구현이 상대적으로 간단하다.
  • Redis 클러스터를 이용하여 확장할 수 있지만, Kafka등에 비춰봤을때 대규모 데이터 처리 자체에는 특화되어 있지는 않다.

Kafka

  • 대용량 데이터를 ‘안정적’으로 주고받고 메시지를 나중에 재처리하거나 활용할 수 있다.
    • 디스크에 실제 메시지가 저장된다.
    • 이로 인해 Consumer는 원하는 타이밍에 해당 데이터를 다시 꺼내볼 수 있다.
  • 메시지의 순서보장, 장애복구, 확장성에 강점이 있다.
  • 상대적으로 Redis pub/sub에 비해서 확장성이 높다.

간략히 위와 같이 Kafka와 Redis pub/sub의 특징을 알아봤습니다.
위 내용으로 미뤄볼때 어떤 메시징 큐를 도입할 지는 다루고 있는 개발자가 풀고자 하는 문제의 요구사항이 무엇인지가 중요하다고 생각됩니다.

도메인과 요구사항의 이해

저의 토이프로젝트는 ‘채팅’이라는 도메인이 서버 내에서 수행하는 역할이 크지 않았습니다.

예를 들어서 치지직 혹은 디스코드 등과 같이 큰 다수의 사용자가 하나의 채팅방에 들어와서 채팅하는 다대다를 지원하지 않았습니다.

대부분의 쇼핑몰(예를 들어 네이버톡)에서 구매자와 사용자가 해당 상품에 대해서 1:1 문의를 하는 내용을 염두에 두고 채팅을 구상하였습니다.

현재 다루고자 하는 문제의 영역인 ‘채팅’ 역시 다른 도메인에 비춰볼때, 상대적으로 데이터가 유실되어도 상관이 없고(중요하지 않다는 것이 아니라 결제, 주문 등에 비춰봤을때 그렇습니다.), 데이터의 실시간성이 훨씬 중요합니다. 또 이 실시간성이 사용자 경험과 크게 연관되어 있다고 생각하였습니다.

이에 따라 저는 현재 토이 프로젝트에서 채팅을 구현함에 있어서 Redis Pub/Sub을 도입하고자 하였습니다. 미들웨어인 Redis Pub/sub로는 메시지 유실이 가능할 수 있기 때문에 채팅 메시지 내역에 대해서는 별도의 ChatMessage로서 DB에 저장하도록 하도록 하였습니다.

이에 따라 Redis Pub/Sub으로 실시간 전송 역할을 수행하고, 이후 DB를 통해서 메시지 로그를 저장하여 실시간성과 영속성을 분리해서 관리하기로 하였습니다.

profile
고민하고 공부하는 사람

0개의 댓글