큐 (Queues)

큐는 RabbitMQ에서 메시지의 순서 있는 집합이에요. 퍼블리셔가 게시한 메시지가 라우팅되어 쌓이고, 컨슈머가 소비하죠. 이번엔 큐 이름·속성·내구성·복제 타입·TTL·정렬 등 큐 전반을 한 번에 잡아둘게요.

출처: Queues | RabbitMQ

본문

RabbitMQ에서 큐는 메시지의 순서 있는 집합이에요. 메시지는 (FIFO, "선입선출") 방식으로 큐에 들어가고(인큐) 큐에서 나와(디큐) 컨슈머에게 전달돼요. 큐를 일반적인 용어로 정의하면, 꼬리에 항목이 추가(인큐)되고 머리에서 꺼내지는(소비) 순차 데이터 구조예요.

큐는 메시징 기술에서 큰 역할을 해요. 많은 메시징 프로토콜·도구가 퍼블리셔와 컨슈머가 큐 같은 저장 메커니즘으로 통신한다고 가정해요. 우선순위나 컨슈머의 재큐잉 같은 기능은 컨슈머가 관찰하는 순서에 영향을 줄 수 있어요.

info: 최신 RabbitMQ 버전은 큐 외에도 스트림·슈퍼 스트림이라는 대체 데이터 구조도 지원해요. 이 가이드는 주로 AMQP 0-9-1 프로토콜 맥락의 큐를 다루지만, 내용 상당수는 다른 지원 프로토콜에도 적용돼요. STOMP·MQTT 같은 일부 프로토콜은 토픽 개념에 기반해요. 이런 프로토콜에서 큐는 컨슈머를 위한 데이터 축적 버퍼로 작동하지만, 그 프로토콜에서도 많은 기능이 큐 레벨에서 동작하므로 큐의 역할을 이해하는 게 여전히 중요해요.

이 주제에서 다루는 내용은:

  • 큐 이름
  • 큐 속성
  • 큐에서의 메시지 정렬
  • 큐 내구성과 메시지 영속성의 관계
  • 복제 큐 타입
  • 클라이언트용 투명 연산 라우팅
  • 일시적·독점 큐
  • 큐 복제본의 런타임 리소스 사용
  • 선택적 큐 인자("x-arguments")
  • 선언과 속성 동등성
  • 큐 지표
  • TTL과 길이 제한
  • 우선순위 큐

컨슈머 관련 주제는 컨슈머 가이드를, classic 큐·quorum 큐·스트림은 각각 전용 가이드를 참고하세요.

큐 이름과 속성

큐에는 애플리케이션이 참조할 수 있는 이름이 있어요. 애플리케이션이 큐 이름을 직접 고르거나 브로커가 생성해 주게 할 수 있어요. 큐 이름은 UTF-8 기준 최대 255바이트예요. amq.로 시작하는 큐 이름은 브로커 내부용으로 예약되어 있어요. 이 규칙을 위반하는 이름으로 큐를 선언하면 403(ACCESS_REFUSED) 응답 코드의 채널 레벨 예외가 발생해요.

AMQP 0-9-1에서 브로커는 애플리케이션 대신 고유한 큐 이름을 생성할 수 있어요. 이 기능을 쓰려면 큐 이름 인자로 빈 문자열을 넘기면 되고, 같은 채널의 이후 메서드에서 큐 이름이 기대되는 자리에 빈 문자열을 쓰면 같은 생성된 이름을 얻을 수 있어요. 채널이 마지막 서버 생성 큐 이름을 기억하기 때문이에요.

서버 명명 큐는 본질적으로 일시적인 상태, 그리고 특정 컨슈머(애플리케이션 인스턴스)에 한정된 상태에 쓰라고 만든 거예요. 애플리케이션은 이런 이름을 메시지 메타데이터에 공유해 다른 애플리케이션이 응답하게 할 수 있어요(튜토리얼 6 참고). 그 외에는 서버 명명 큐의 이름은 선언한 애플리케이션 인스턴스만 알고 사용해야 해요. 그 인스턴스는 큐에 적절한 바인딩(라우팅)을 설정해서, 퍼블리셔가 서버 생성 큐 이름을 직접 쓰기보다 잘 알려진 익스체인지를 쓰게 하는 게 좋아요.

큐에는 동작을 정의하는 속성이 있어요. 필수 속성 집합과 선택적 속성 맵이 있죠.

  • 이름
  • 내구성(Durable, 큐가 브로커 재시작에도 살아남음)
  • 독점성(Exclusive, 한 연결만 사용하고 연결이 닫히면 삭제됨)
  • 자동 삭제(Auto-delete, 컨슈머가 한 번이라도 있었던 큐는 마지막 컨슈머가 구독 해제할 때 삭제)
  • 인자(Arguments, 선택적, 메시지 TTL·큐 길이 제한 같은 플러그인·브로커 특정 기능용)

important: 모든 속성 조합이 말이 되는 건 아니에요. 예를 들어 독점 큐는 거의 항상 서버 명명이어야 해요. 그런 큐는 클라이언트 특정 또는 연결(세션) 특정 데이터에 쓰라고 만든 거예요. 독점 큐가 잘 알려진(정적) 이름을 쓰면, 클라이언트 연결 해제 후 즉시 재연결할 때 RabbitMQ 노드가 큐를 삭제하는 것과, 복구하는 클라이언트가 재선언하려는 것 사이에 자연스러운 경쟁 조건이 생겨요. 이는 클라이언트 측 연결 복구 실패나 예외로 이어질 수 있어 애플리케이션 가용성에 혼란을 주거나 영향을 줄 수 있어요.

tip: 특히 큐 타입 속성은 속성 동등성 검사를 완화할 수 있어요. 또는 기본 큐 타입(DQT)을 설정할 수도 있어요.

큐 선언

큐를 사용하려면 먼저 선언해야 해요. 선언하면 큐가 아직 없을 때는 생성되고, 이미 존재하고 속성이 선언과 같으면 아무 효과가 없어요. 기존 큐 속성이 선언과 다르면 406(PRECONDITION_FAILED) 코드의 채널 레벨 예외가 발생해요. 특히 큐 타입 속성은 속성 동등성 검사를 완화하거나 기본값을 쓰도록 설정할 수 있어요. 자세한 내용은 가상 호스트 가이드를 참고하세요.

선택적 큐 인자(AMQP 0-9-1 프로토콜의 필드명 때문에 "x-arguments"라고 불러요)는 큐를 선언할 때 클라이언트가 제공할 수 있는 임의의 키/값 쌍 맵(딕셔너리)이에요. 다양한 기능·플러그인이 이 맵을 사용해요.

이 아이디어는 컨슈머 등록 같은 다른 프로토콜 연산에도 쓰여요(예: 컨슈머 우선순위). 일부 선택적 인자는 큐 선언 시점에 설정되어 큐 수명 내내 변경할 수 없어요. 다른 인자는 큐 선언 후 폴리시로 동적으로 변경할 수 있어요.

tip: 폴리시로 설정할 수 있는 키는 애플리케이션 코드에 값을 설정하기보다 항상 폴리시를 먼저 고려하세요. 예를 들어 큐 타입(x-queue-type)과 최대 큐 우선순위 수(x-max-priority)는 큐 선언 시점에 설정해야 하고 이후 변경할 수 없어요.

선택적 큐 인자는 다르게 설정할 수 있어요.

  • 폴리시로 큐 그룹에 적용(권장)
  • 클라이언트가 큐를 선언할 때 큐별로 적용
  • x-queue-type 인자의 경우 기본 큐 타입 사용

전자가 더 유연하고 간섭이 적으며 애플리케이션 수정·재배포가 필요 없어요. 대부분의 사용자에게 강력히 권장돼요. 다만 큐 타입이나 최대 우선순위 수 같은 일부 선택적 인자는 동적으로 변경할 수 없고 선언 시점에 알아야 하므로 클라이언트만 제공할 수 있어요.

클라이언트가 선택적 인자를 제공하는 방식은 라이브러리마다 다르지만, 보통 큐를 선언하는 함수(메서드)의 durable, auto_delete 등 인자 옆에 제공돼요. 같은 키가 클라이언트 제공 x-arguments폴리시 양쪽에 있으면 전자가 우선해요. 운영자 폴리시가 사용 중이면 그게 클라이언트 제공 인자보다도 우선해요. 숫자 값(최대 큐 길이TTL 같은)은 둘 중 더 낮은 값이 사용돼요. 운영자 폴리시는 리소스 사용(예: 최대 디스크 공간)과 관련된 애플리케이션 제어 파라미터에 가드레일을 도입할 때 유용해요.

메시지 정렬

메시지 사이에 인과 의존성이 있으면 정렬이 중요해요. RabbitMQ는 메시지의 순서를 보존하려고 노력해요. 큐는 FIFO 의미론을 제공하는 순서 있는 메시지 집합이에요. 하나의 채널에서 게시하면 메시지는 라우팅되는 모든 큐에 게시 순서대로 인큐돼요. 여러 연결·채널에서 게시하면 그 메시지 시퀀스는 동시에 라우팅되고 서로 섞여요. 큐에서 컨슈머로의 전달은 인큐 순서대로 진행돼요(아래 이벤트가 없다면).

RabbitMQ가 순서 보존을 목표로 해도, 다음은 유효 전달 순서를 바꿔요.

  1. 메시지 우선순위: 높은 우선순위 메시지가 낮은 우선순위 메시지보다 먼저 전달될 수 있어요
  2. 같은 큐의 여러 활성 컨슈머: 브로커는 여전히 FIFO로 디큐하지만, 재전송이 순서를 바꿀 수 있어요. 재전송은 컨슈머가 requeue로 부정 인정하거나 채널/세션이 인정되지 않은 메시지를 남긴 채 닫힐 때 일어나요. 재전송된 메시지에는 플래그가 붙어요(AMQP 1.0: first-acquirer=false, AMQP 0-9-1: redelivered=true)

RabbitMQ에서 메시지 순서를 보존하는 방법은 두 가지예요. 스트림은 추가 전용 불변 로그예요. 각 메시지는 게시 시점에 오프셋을 배정받고, 이 오프셋은 절대 변하지 않아요. 여러 컨슈머가 같은 스트림을 동시에 처리해도 순서에 영향이 없어요. 스트림 필터링으로 서로 다른 컨슈머가 스트림의 서로소 부분집합을 처리하면서 각 부분집합 내 순서를 보존하게 작업을 나눌 수 있어요.

큐로 순서를 지키려면:

  • 단일 활성 컨슈머를 켜서 한 번에 한 컨슈머만 메시지를 받게 해요(또는 큐마다 컨슈머 하나씩 운영)
  • 컨슈머가 메시지를 큐에 돌려주면, 받은 순서대로 돌려줘야 해요
  • quorum 큐에서는 전달 제한을 설정해서 메시지가 큐 앞쪽에 재큐잉되게 해요
  • AMQP 0-9-1: basic.get을 쓰지 마세요. 컨슈머를 멈출 때는 basic.cancel보다 채널을 닫는 걸 선호하세요

루프 백팩로그에 밀려나는 것을 처리하기 위해 x-modulus-hash 익스체인지를 사용할 수 있어요. 각 도메인 엔티티(예: 주문 ID)별로 순서를 보존하며 메시지를 동시에 처리해야 한다면, 이 익스체인지로 메시지를 여러 큐로 파티셔닝하고 각 큐에 단일 활성 컨슈머를 두면 돼요.

내구성과 영속성

큐는 내구성 또는 일시적(비내구성)일 수 있어요. 내구성 큐의 메타데이터는 디스크에, 일시적 큐의 메타데이터는 가능하면 메모리에 저장돼요. 메시지에도 게시 시점에 같은 구분이 적용되는 프로토콜(예: AMQP 0-9-1, MQTT)이 있어요.

내구성이 중요한 환경·사용 사례에서는 애플리케이션이 내구성 큐를 사용하고, 퍼블리셔가 게시한 메시지를 영속(persisted)으로 표시하도록 해야 해요. 내구성 큐는 노드 부팅 시 복구되며, 그 안의 영속으로 게시된 메시지도 함께 복구돼요. 일시적(transient)으로 게시된 메시지는 내구성 큐에 저장되어 있어도 복구 중 폐기돼요. 일시적 큐는 노드 부팅 시 삭제되므로, 설계상 노드 재시작에도 살아남지 못해요. 일시적 큐의 메시지도 함께 폐기돼요.

warning: 일시적(비내구성) 비독점 classic 큐는 폐기 예정이며 RabbitMQ 4.3.0부터 기본적으로 선언할 수 없어요. 다음 중 하나를 쓰세요.

  • 내구성 큐
  • 비내구성 독점 큐
  • 큐 TTL이 있는 내구성 큐(비독점 일시적 큐와 합리적으로 동등한 대안)

일시적 비독점 큐를 명시적으로 허용하려면 rabbitmq.conf에 다음 줄을 추가하세요.

# 4.3.0부터 기본 비활성, 이후 버전에서 제거 예정인
# 비내구성(일시적) 비독점 큐를 허용
deprecated_features.permit.transient_nonexcl_queues = true

대부분의 경우 내구성 큐가 권장되어요. 복제 큐에서는 내구성 큐만이 합리적 선택이에요. 큐의 처리량·지연은 대부분의 경우 내구성 여부에 영향받지 않아요. 큐·바인딩이 초당 수백 번 이상 삭제·재선언되는 매우 높은 변동 환경에서만 일부 연산(특히 바인딩)의 지연이 개선돼요. 내구성·일시적 선택은 사용 사례의 의미론에 달려 있어요.

일시적 큐는 일시적 클라이언트가 있는 워크로드에 합리적 선택일 수 있어요. 예를 들어 UI의 일시적 WebSocket 연결, 오프라인이 되거나 신원을 바꾸는 모바일 기기·기기가 그렇죠. 그런 클라이언트는 본래 재연결 시 대체되어야 하는 일시적 상태를 가져요. 일부 큐 타입은 일시적 큐를 지원하지 않아요. quorum 큐는 기반 복제 프로토콜의 가정·요구 때문에 반드시 내구성이어야 해요.

자동 삭제·독점 큐

일부 워크로드에서 큐는 짧은 수명이어야 해요. 클라이언트가 연결 해제 전에 선언한 큐를 삭제할 수 있지만 항상 편리한 건 아니에요. 게다가 클라이언트 연결이 실패하면 사용하지 않는 리소스(큐)가 남을 수 있어요. RabbitMQ는 본질적으로 일시적이거나 클라이언트 특정인 데이터에 맞는 큐 속성을 여럿 지원해요. 일부 설정은 내구성 큐에도 적용할 수 있지만 모든 조합이 말이 되진 않아요.

tip: 독점 일시적 큐에는 서버 생성 이름을 쓰는 걸 고려하세요. 그런 큐는 N개 컨슈머 간에 공유하라고 만든 게 아니므로 고유 이름을 쓰는 게 말이 되요.

큐가 자동으로 삭제되는 방식은 세 가지예요.

  • 독점 큐(아래에서 다룸)
  • TTL(아래에서 다룸)
  • 자동 삭제 큐

자동 삭제 큐는 마지막 컨슈머가 취소될 때(예: AMQP 0-9-1 basic.cancel) 또는 사라질 때(채널·연결이 닫히거나 TCP 연결이 끊김) 삭제돼요. 컨슈머가 한 번도 없었던 큐, 예를 들어 모든 소비가 폴링으로 일어나는 큐는 자동 삭제되지 않아요. 그런 경우에는 독점 큐나 큐 TTL을 쓰세요.

warning: RabbitMQ가 비내구성·비독점 큐를 감지하면 관리 UI에 폐기 경고를 표시해요(위의 4.3.0부터 기본 비활성 정책과 동일).

큐 TTL은 사용하지 않는 내구성 큐 정리에 쓸 수 있어요.

독점 큐는 선언한 연결만 사용(소비·퍼지·삭제 등)할 수 있어요. 이런 큐는 정의상 일시적인데, 내구성 큐에 exclusive 속성을 두는 건 논리적으로 말이 안 돼요. 그런 큐는 선언한 연결보다 오래 살 수 없어 노드 재시작 시 내구성을 만족시킬 수 없거든요. 독점으로 선언된 큐는 항상 classic 큐로 선언돼요. 독점 quorum 큐·스트림은 수명이 특정 클라이언트 연결(따라서 단일 노드·애플리케이션 인스턴스)에 묶여 논리적으로 말이 안 되기 때문이에요.

tip: 독점 큐에는 서버 생성 이름을 쓰는 걸 고려하세요. N개 컨슈머가 공유할 수 없으므로 서버 생성 이름이 가장 말이 돼요.

다른 연결에서 독점 큐에 접근하려 하면 cannot obtain exclusive access to locked queue라는 메시지와 함께 RESOURCE_LOCKED 채널 레벨 예외가 발생해요. 독점 큐는 선언한 연결이 닫히거나 사라지면(예: TCP 연결 유실) 삭제돼요. 그래서 클라이언트 특정 일시 상태에만 적합해요. 독점 큐는 서버 명명으로 만드는 게 흔해요. 독점 큐는 큐를 선언하는 클라이언트가 연결된 "클라이언트-로컬" 노드에 선언되고, queue_leader_locator 값과 무관해요.

복제·라우팅

quorum 큐는 복제·데이터 안전·일관성 중심의 큐 타입이에요. classic 큐는 역사적으로 복제를 지원했지만 이 기능은 RabbitMQ 4.x에서 제거됐어요.

어떤 연결의 클라이언트든 큐가 복제됐든 아니든, 큐 복제본이 호스팅된 노드나 클라이언트가 연결된 노드와 무관하게 어떤 큐든 사용할 수 있어요. RabbitMQ는 클라이언트에게 투명하게 연산을 적절한 노드로 라우팅해요. 예를 들어 A·B·C 노드 클러스터에서 노드 A에 연결된 클라이언트가 B에 호스팅된 큐 Q에서 소비할 수 있고, C에 연결된 클라이언트도 큐 Q로 메시지가 라우팅되게 게시할 수 있어요. 클라이언트 라이브러리나 애플리케이션은 데이터 지역성을 높이기 위해 특정 큐의 현재 리더 복제본을 호스팅하는 노드에 연결하기로 정할 수 있어요.

이 일반 규칙은 RabbitMQ가 지원하는 모든 메시징 데이터 타입에 적용되고, 예외가 하나 있어요. 스트림이 그 예외로, 프로토콜과 무관하게 클라이언트가 대상 스트림의 복제본(리더 또는 팔로워)을 호스팅하는 노드에 연결해야 해요. 그래서 RabbitMQ Stream 프로토콜 클라이언트는 여러 노드에 병렬로 연결해요.

큐는 느슨하게 결합된 노드·클러스터 간에 연합(federated)될 수도 있어요. 클러스터 내 복제와 연합은 직교 기능이므로 직접적인 대안으로 보면 안 돼요.

리소스 제한·우선순위

큐는 길이를 제한할 수 있고, 큐·메시지는 TTL을 가질 수 있어요. 두 기능 모두 데이터 만료와, 큐가 최대로 쓸 리소스(RAM·디스크 공간)를 제한하는 방법으로 쓸 수 있어요. 예를 들어 컨슈머가 오프라인이거나 처리량이 게시자에 뒤처질 때요. 최신 RabbitMQ 버전에서 quorum 큐와 classic 큐 v2는 모두 데이터를 적극적으로 디스크로 옮기고 비교적 작은 작업 집합만 메모리에 유지해요.

일부 프로토콜(예: AMQP 0-9-1)에서 클라이언트는 메시지를 영속 또는 일시적으로 게시할 수 있어요. 일시적 메시지도 디스크에 저장되지만 다음 노드 재시작 때 폐기돼요. AMQP 0-9-1에서는 메시지 속성(delivery_mode 또는 일부 클라이언트의 persistent)으로 이걸 해요. 관련 가이드는 Quorum 큐·스트림·메모리 사용 추론·알람·메모리 알람·디스크 공간 알람·배포 가이드라인·메시지 스토어 설정이에요.

큐는 우선순위를 0개 이상 가질 수 있어요. 이 기능은 옵트인(opt-in)이에요. 선택적 인자로 최대 우선순위 수가 설정된 큐만 우선순위를 수행해요. 퍼블리셔는 메시지 속성의 priority 필드로 메시지 우선순위를 지정해요. 우선순위 큐를 원하면 1~10 사이를 권장해요. 더 많은 우선순위를 쓰면 더 많은 리소스(Erlang 프로세스)를 소비해요.

현재 큐 복제본 하나(리더든 팔로워든)는 핫 코드 경로에서 단일 CPU 코어로 제한돼요. 이 설계는 대부분의 시스템이 실제로 여러 큐를 사용한다고 가정해요.

danger: 단일 큐는 일반적으로 안티패턴으로 간주돼요. 리소스 사용 이유만이 아니에요. 큐 처리량을 한계까지 밀어붙이는 워크로드에서는 스트림·파티셔닝된 스트림RabbitMQ Stream 프로토콜 클라이언트와 함께 사용하는 걸 고려하세요.

큐 지표와 소비에 관해

RabbitMQ는 큐에 대한 여러 지표를 수집해요. 대부분 RabbitMQ HTTP API와 관리 UI로 볼 수 있고, 모니터링용으로 설계됐어요. 큐 길이, 인그레스·이그레스 속도, 컨슈머 수, 다양한 상태의 메시지 수(예: 전달 준비 상태 또는 미인정), RAM vs 디스크 메시지 수 등을 포함해요. rabbitmqctl로 큐와 기본 지표를 나열할 수 있어요. VM 스케줄러 사용·큐(Erlang) 프로세스 GC 활동·큐 프로세스가 쓰는 RAM·큐 프로세스 사서함 길이 같은 런타임 지표는 rabbitmq-top 플러그인과 관리 UI의 개별 큐 페이지로 볼 수 있어요.

메시지는 컨슈머(구독)를 등록해서 소비할 수 있어요. 그러면 RabbitMQ가 메시지를 클라이언트로 푸시하고, 또는 해당 프로토콜이 지원하면(예: AMQP 0-9-1의 basic.get 메서드) HTTP GET처럼 메시지를 개별로 가져올 수 있어요.

전달된 메시지는 컨슈머가 명시적으로 인정하거나, 전달이 연결 소켓에 쓰이는 즉시 자동으로 인정될 수 있어요. 자동 인정 모드는 일반적으로 더 높은 처리량과 더 적은 네트워크 대역폭을 제공해요. 하지만 실패 측면에서 가장 적은 보장을 제공해요. 경험 법칙으로, 먼저 수동 인정 모드를 고려하세요. 자동 인정 모드는 전달 속도를 따라잡지 못하는 컨슈머를 압도할 수도 있어요. 컨슈머 프로세스의 메모리 사용이 영구히 늘거나 OS 스와핑이 생길 수 있죠. 수동 인정 모드는 미해결(미확인) 전달 수에 제한을 두는 방법(채널 QoS, prefetch)을 제공해요. 높은(수천 개 이상) prefetch 레벨을 쓰는 컨슈머는 자동 인정 컨슈머와 같은 과부하 문제를 겪을 수 있어요. 미인정 메시지가 많으면 브로커의 메모리 사용도 늘어요.

따라서 인큐된 메시지는 두 상태 중 하나일 수 있어요.

상태별 메시지 내역은 관리 UI에서 볼 수 있어요. 큐 길이는 여러 방식으로 결정할 수 있어요.

  • AMQP 0-9-1: queue.declare 메서드 응답(queue.declare-ok)의 속성 사용. 필드명은 message_count이고, 접근 방식은 클라이언트 라이브러리마다 달라요
  • RabbitMQ HTTP API 사용
  • rabbitmqctl list_queues 명령 사용

큐 길이는 전달 준비 상태의 메시지 수로 정의돼요.

일시적 큐의 경쟁 조건

독점이 아닌 일시적 큐는 클라이언트가 이름을 정해 여러 컨슈머가 공유할 수 있어요. 하지만 이는 권장되지 않고 RabbitMQ 노드 연산과 클라이언트 복구 사이에 경쟁 조건을 만들 수 있어요. 다음 시나리오를 생각해 보세요.

  • 컨슈머가 잘 알려진 이름의 자동 삭제 큐를 사용함
  • 클라이언트 연결이 실패함
  • 클라이언트가 감지하고 연결 복구를 시작함

유일한 컨슈머가 있던 연결이 실패했으므로, 자동 삭제 큐는 RabbitMQ가 삭제해야 해요. 이 연산에 시간이 걸리고, 그동안 컨슈머가 복구될 수 있어요. 그러면 연산 타이밍에 따라 큐는:

  1. 복구하는 클라이언트가 선언한 뒤 삭제되거나
  2. 삭제된 뒤 다시 선언되거나

첫 번째 경우, 클라이언트는 동시에 삭제된 큐에 컨슈머를 다시 등록하려 하다 채널 예외를 만나요. 이 근본적 경쟁 조건에는 해결책이 두 가지 있어요.

  1. 연결 복구 지연 도입. 예를 들어 여러 RabbitMQ 클라이언트 라이브러리가 기본적으로 5초의 연결 복구 지연을 써요
  2. 서버 명명 큐 사용. 새 클라이언트 연결이 이전과 다른 큐 이름을 쓰게 되므로 문제를 완전히 우회해요

더 알아보기