Message Queue
Message Queue는 생산자가 보낸 작업 메시지를 소비자가 준비됐을 때 순서대로 꺼내 처리하도록 중간에 잡아 두는 비동기 작업 버퍼입니다. 생산 속도와 처리 속도가 달라도 어느 쪽도 상대를 직접 기다리지 않아도 되고, 소비자가 잠시 다운됐다 복구되더라도 큐에 쌓인 메시지를 이어서 처리할 수 있습니다.
▶아키텍처 다이어그램
📊 데이터 흐름 다이어그램점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다
이메일 발송이나 이미지 변환처럼 수 초가 걸리는 작업을 사용자 요청 경로 안에서 직접 처리하면 응답 시간이 그만큼 길어집니다. 트래픽이 갑자기 몰릴 때는 하위 처리 서비스가 따라가지 못해 요청이 타임아웃되거나 통째로 실패합니다. 실패한 작업을 어떻게 다시 처리할지 기준도 없으면 재시도 루프가 오히려 과부하를 키웁니다. 이런 상황에서 생산과 소비를 분리할 버퍼 없이 속도 차이를 코드 안에서만 다루려 하면, 시스템은 조용히 버티다가 한계에서 한꺼번에 깨집니다.
초기 웹 시스템은 대부분 요청이 들어오는 순간 처리를 끝내는 동기 방식이었습니다. 서비스 규모가 커지고 백그라운드 작업의 종류가 다양해지면서, 사용자가 기다리는 경로와 처리가 걸리는 경로를 한곳에서 처리하는 방식이 불안정해졌습니다. 처리 지연이 응답 지연으로 그대로 번지고, 일시 장애가 데이터 손실로 이어졌습니다. 운영자들은 수신은 즉시 확인하고 실제 처리는 여유 있을 때 하는 방식을 원하게 됐습니다. Message Queue는 생산과 소비의 시간적 결합을 끊어내는 방향으로 그 자리를 채우게 됐습니다.
생산자는 메시지를 큐에 넣고 즉시 다음 작업으로 넘어갑니다. 큐는 메시지를 보관하고, 소비자는 자신의 처리 용량에 맞게 꺼내 갑니다. 소비자가 여럿이면 메시지를 병렬로 나눠 처리할 수 있고, 처리에 실패한 메시지는 재시도하거나 별도 격리 경로로 분리됩니다. 큐가 메시지를 보관하는 동안에는 소비자의 다운이 곧 데이터 손실을 뜻하지 않습니다. 처리 속도가 다른 두 쪽을 큐 하나가 중간에서 완충해 줍니다.
Message Queue와 Publish/Subscribe는 모두 메시징 구조이지만 용도가 다릅니다. Message Queue는 메시지 하나를 소비자 중 누군가가 가져가 처리하는 작업 분배 모델로, 처리율 제어와 재시도 관리가 중심입니다. Publish/Subscribe는 메시지 하나를 여러 구독자가 동시에 받는 fan-out 모델로, 사건에 대한 독립적인 반응 확장이 중심입니다. 이메일 발송 큐처럼 누군가 하나가 처리하면 되는 작업이라면 Queue가 맞고, 주문 완료를 여러 시스템이 동시에 알아야 하는 사건이라면 Pub/Sub가 맞습니다.
응답 시간에 여유가 없는 요청 경로에서 무거운 작업을 분리하고 싶을 때, 트래픽 급증을 흡수할 버퍼가 필요할 때, 여러 워커가 동시에 작업을 처리해야 할 때가 Message Queue를 도입할 신호입니다. 특히 이메일 발송, 파일 변환, 외부 API 호출처럼 처리 시간이 불확실하거나 실패 가능성이 있는 작업에 잘 맞습니다. 단, 큐를 도입하면 처리 완료 여부를 요청 경로 안에서 바로 알 수 없게 되므로, 처리 결과를 추적하는 방법과 같은 메시지가 두 번 처리되더라도 결과가 달라지지 않도록 하는 안전성을 함께 설계해야 합니다.