본문 바로가기
1. 개발/1.8. ActiveMQ

JMS 전용 속성(JMSX로 시작하는 속성)의 종류와 활용법은?

by 엉짱 2026. 3. 16.
반응형

JMS 전용 속성(JMSX로 시작하는 속성)의 종류와 활용법은?

JMS(Java Message Service) 스펙은 메시지의 메타데이터를 표현하기 위해 표준 헤더(JMSMessageID, JMSTimestamp 등) 외에도 추가적인 확장 속성들을 정의하고 있습니다. 이 확장 속성들은 모두 JMSX라는 접두사로 시작하며, 메시지 브로커와 클라이언트 간의 고급 라우팅, 상태 추적, 보안, 순서 보장 등의 복잡한 엔터프라이즈 요구사항을 해결하는 데 핵심적인 역할을 합니다.

JMS 스펙에 정의된 JMSX 속성들은 메시징 벤더(ActiveMQ, Artemis, IBM MQ 등)에 따라 필수적으로 지원해야 하는 속성과 선택적으로 지원하는 속성으로 나뉩니다. 실무에서 아키텍처를 설계할 때 반드시 알아두어야 할 주요 JMSX 속성의 종류와 그 구체적인 활용법을 분석합니다.


1. 순서 보장과 병렬 처리의 핵심: JMSXGroupID 및 JMSXGroupSeq

가장 널리 쓰이고 중요한 속성입니다. 여러 컨슈머가 큐를 공유하는 분산 환경에서 특정 연관된 메시지들의 처리 순서를 엄격히 보장하기 위해 사용됩니다(Message Groups 기능).

  • JMSXGroupID (String):
  • 의미: 동일한 논리적 그룹(예: 동일한 주문 번호 ORDER-1234)에 속하는 메시지들을 식별합니다.
  • 활용법: 생산자(Producer)가 이 속성에 동일한 값을 세팅하여 브로커로 전송하면, 브로커는 해당 JMSXGroupID를 가진 모든 메시지를 큐에 연결된 여러 컨슈머 중 오직 단 하나의 컨슈머에게만 전담하여 라우팅합니다. 이를 통해 동시성 충돌을 막고 완벽한 순서를 보장할 수 있습니다.
  • JMSXGroupSeq (Integer):
  • 의미: JMSXGroupID로 묶인 그룹 내에서 해당 메시지의 일련번호를 나타냅니다.
  • 활용법: 일반적으로 1부터 시작하여 양수로 증가합니다. 가장 중요한 활용법은 그룹을 명시적으로 종료할 때입니다. 생산자가 비즈니스 트랜잭션의 마지막 메시지에 JMSXGroupSeq = -1 (혹은 0 등 브로커 설정값)을 부여하여 전송하면, 브로커는 해당 그룹의 소유권(Ownership) 매핑을 메모리에서 해제하여 메모리 누수를 방지하고 컨슈머 리밸런싱을 돕습니다.

2. 독성 메시지(Poison Pill) 방지와 재처리 추적: JMSXDeliveryCount

네트워크 장애나 컨슈머의 비즈니스 로직 오류로 인해 메시지 처리가 실패(Rollback)하면, 브로커는 해당 메시지를 재전송(Redelivery)합니다. 이때 무한 재시도로 인한 시스템 마비를 막기 위해 필수적인 속성입니다.

  • JMSXDeliveryCount (Integer):
  • 의미: 브로커가 해당 메시지를 컨슈머에게 전달하려고 시도한 총 횟수입니다.
  • 활용법: 이 값은 생산자가 세팅하는 것이 아니라, 브로커가 메시지를 큐에서 꺼내 컨슈머로 내려보낼 때마다 1씩 자동 증가시킵니다. 컨슈머 애플리케이션은 메시지를 수신했을 때 message.getIntProperty("JMSXDeliveryCount")를 호출하여 몇 번째 재시도인지 확인할 수 있습니다. 만약 이 값이 브로커에 설정된 최대 재시도 횟수(예: 5)에 도달하면, 브로커는 해당 메시지를 DLQ(Dead Letter Queue)로 강제 이동시켜 전체 큐의 선두 차단(Head-of-Line Blocking) 현상을 방지합니다.

3. 보안 및 감사(Audit) 트레일링: JMSXUserID 및 JMSXAppID

엔터프라이즈 환경에서는 누가, 어떤 시스템에서 메시지를 발행했는지 추적(Tracing)하고 인가(Authorization)를 검증하는 작업이 매우 중요합니다.

  • JMSXUserID (String):
  • 의미: 메시지를 전송한 사용자(또는 시스템 계정)의 식별자입니다.
  • 활용법: 클라이언트가 임의로 조작하는 것을 막기 위해, 브로커 설정(예: ActiveMQ의 populateJMSXUserID=true)을 통해 브로커가 직접 연결된 세션의 인증 정보를 바탕으로 덮어쓰도록 강제할 수 있습니다. 이를 통해 컨슈머는 메시지의 출처를 100% 신뢰할 수 있으며, 악의적인 메시지 발행을 차단할 수 있습니다.
  • JMSXAppID (String):
  • 의미: 메시지를 생성하고 전송한 애플리케이션의 고유 식별자입니다.
  • 활용법: 여러 종류의 마이크로서비스가 단일 브로커를 공유할 때, 메시지의 발생지를 특정하거나 분산 트레이싱(Distributed Tracing) 로그를 남길 때 유용하게 활용됩니다.

4. 트랜잭션 및 타임스탬프 관련 추가 속성

상대적으로 사용 빈도는 낮지만, 특정 벤더나 복잡한 분산 트랜잭션(XA) 환경에서 활용되는 속성들입니다.

  • JMSXProducerTXID / JMSXConsumerTXID (String):
  • 메시지가 생산되거나 소비될 때 속해 있던 트랜잭션의 식별자입니다. 분산 환경에서 글로벌 트랜잭션의 롤백 및 커밋 로그를 추적하여 데이터 정합성을 감사할 때 사용됩니다.
  • JMSXRcvTimestamp (Long):
  • 생산자가 메시지를 생성한 시간(JMSTimestamp)과 달리, 브로커가 해당 메시지를 컨슈머에게 물리적으로 '전달(Deliver)'한 시점의 타임스탬프입니다. 메시지가 큐에서 얼마나 오래 대기했는지, 네트워크 지연 시간이 얼마나 발생했는지 등 시스템 레이턴시(Latency)를 모니터링하는 지표로 활용됩니다.
  • JMSXState (Integer):
  • 브로커 내부에서 메시지의 현재 상태(Waiting, Ready, Retained 등)를 나타냅니다. 주로 브로커의 관리자 콘솔(Admin UI)이나 JMX 모니터링 툴에서 큐의 상태를 시각화할 때 내부적으로 사용됩니다.

5. JMSX 속성 사용 시의 아키텍처 설계 주의사항

  1. 벤더 종속성 확인: JMS 스펙은 JMSXGroupIDJMSXDeliveryCount 등 일부 속성의 지원을 필수(Mandatory)로 강제하지만, JMSXUserID, JMSXAppID, JMSXProducerTXID 등 상당수는 벤더의 선택(Optional) 사항입니다. 따라서 브로커를 교체할 때 해당 속성이 정상적으로 동작하는지 반드시 사전 검증해야 합니다.
  2. 보안 속성의 무결성 보장: JMSXUserID와 같은 보안 속성은 절대 클라이언트(생산자)의 코드를 전적으로 신뢰해서는 안 됩니다. 반드시 브로커 단에서 세션 정보를 가로채어 검증하고 주입(Populate)하는 플러그인 설정을 활성화해야 스푸핑(Spoofing) 공격을 막을 수 있습니다.
  3. 셀렉터(Selector)와의 결합: 컨슈머는 메시지 셀렉터를 작성할 때 JMSX 속성을 일반 사용자 정의 속성처럼 조건문(WHERE)에 사용할 수 있습니다. (예: JMSXDeliveryCount > 2). 이를 활용하면 "2번 이상 실패한 메시지만 별도로 수집하여 분석하는 전용 모니터링 컨슈머"를 라우팅 비용 없이 손쉽게 구축할 수 있습니다.
반응형