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

Artemis의 'Divert' 기능을 이용한 메시지 변환 및 복제 시나리오는?

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

Artemis의 'Divert' 기능을 이용한 메시지 변환 및 복제 시나리오는?

마이크로서비스 아키텍처(MSA)나 복잡한 엔터프라이즈 통합 환경(EAI)에서는 이미 구축된 생산자(Producer)와 소비자(Consumer)의 코드를 수정하지 않고 브로커 내부에서 메시지의 흐름을 제어하거나 데이터를 가공해야 하는 요구사항이 빈번하게 발생합니다.

ActiveMQ Artemis는 이러한 아키텍처적 난제를 해결하기 위해 브로커 레벨에서 투명하게 메시지를 가로채어 다른 주소로 라우팅하거나 본문을 변환할 수 있는 Divert(다이버트) 기능을 제공합니다. Divert는 클라이언트 애플리케이션의 인지 없이 브로커 내부 메모리에서 직접 동작하므로 극도로 빠르고 효율적입니다.

이 가이드에서는 Divert의 두 가지 핵심 라우팅 방식과 Transformer를 결합한 실무 메시지 처리 시나리오를 상세히 분석합니다.


1. Exclusive Divert: 메시지 흐름의 완전한 분기 및 가로채기

Exclusive(독점적) Divert는 원본 주소(Address)로 들어온 메시지를 완전히 가로채어 지정된 대상 주소(Forward Address)로만 라우팅합니다. 원본 주소에 바인딩된 큐(Queue)에는 메시지가 전혀 전달되지 않습니다.

  • 동작 매커니즘: 라우터나 스위치에서 트래픽의 경로를 완전히 틀어버리는 것과 같습니다. 메시지 셀렉터(Filter)를 결합하면 특정 조건을 만족하는 메시지만 분기시킬 수 있습니다.
  • 설정 방식 (broker.xml):
    <diverts>
     <divert name="vip-order-divert">
        <address>orders.global</address>
        <forwarding-address>orders.vip.priority</forwarding-address>
        <filter string="customerTier = 'VIP'"/>
        <exclusive>true</exclusive>
     </divert>
    </diverts>
    


* **실무 적용 시나리오 (버전 마이그레이션 및 트래픽 격리):**
기존에 `orders.global` 주소로 모든 주문을 보내던 레거시 프로듀서가 있습니다. 백엔드 시스템을 개편하면서 VIP 고객의 주문은 새로운 고성능 처리 시스템(`orders.vip.priority`)에서 전담하도록 아키텍처를 변경했습니다.
이때 레거시 프로듀서의 코드를 수정하여 분기 로직을 넣는 대신, 브로커에 Exclusive Divert를 설정합니다. VIP 주문 메시지는 기존 큐에 들어가지 않고 투명하게 새로운 시스템으로 흘러가며, 일반 주문은 기존 큐에 그대로 남게 되어 완벽한 트래픽 격리(Isolation)가 달성됩니다.

---

### 2. Non-Exclusive Divert: 메시지 복제 및 와이어 탭(Wire Tap) 패턴

**Non-Exclusive(비독점적) Divert**는 원본 주소로 들어온 메시지의 흐름을 방해하지 않고, 메시지의 복사본(Copy)을 생성하여 대상 주소로 전달합니다. 엔터프라이즈 통합 패턴(EIP)의 **Wire Tap(와이어 탭)** 패턴을 브로커 단에서 구현한 것입니다.

* **동작 매커니즘:** 메시지는 원래 가야 할 큐에도 정상적으로 적재되고, 동시에 지정된 다른 주소로도 복제되어 전송됩니다.
* **설정 방식 (`broker.xml`):**
```xml
<diverts>
   <divert name="order-audit-divert">
      <address>orders.global</address>
      <forwarding-address>audit.logging.queue</forwarding-address>
      <exclusive>false</exclusive>
   </divert>
</diverts>
  • 실무 적용 시나리오 (실시간 감사 로그 및 데이터 레이크 적재):
    주문 결제 시스템이 메인 비즈니스 로직을 처리하는 동안, 사내 보안팀에서 "모든 결제 트랜잭션의 원본 데이터를 감사(Audit) 시스템으로 실시간 전송해 달라"는 요구를 추가했습니다.
    메인 주문 큐(orders.global)에 Non-Exclusive Divert를 걸어두면, 메인 시스템의 처리 속도나 로직에 어떠한 부하나 영향도 주지 않으면서 모든 메시지의 복제본이 audit.logging.queue로 흘러가게 됩니다. 이를 통해 메인 비즈니스 파이프라인과 데이터 수집 파이프라인을 아키텍처 레벨에서 완벽하게 디커플링(Decoupling)할 수 있습니다.

3. Transformer를 이용한 런타임 메시지 변환 (Message Transformation)

Divert의 진정한 강력함은 단순한 복제/분기를 넘어, 라우팅되는 찰나의 순간에 메시지의 헤더(Properties)나 본문(Payload)을 조작할 수 있는 Transformer 기능과 결합할 때 발휘됩니다.

  • 동작 매커니즘: Divert 설정 내에 org.apache.activemq.artemis.core.server.cluster.Transformer 인터페이스를 구현한 사용자 정의 Java 클래스를 지정합니다. 브로커는 메시지를 Forwarding 하기 직전에 이 클래스의 transform() 메서드를 호출합니다.
  • 설정 방식 (broker.xml):
    <diverts>
     <divert name="legacy-adapter-divert">
        <address>modern.events</address>
        <forwarding-address>legacy.system.queue</forwarding-address>
        <exclusive>false</exclusive>
        <transformer-class-name>com.mycompany.messaging.FormatAdapterTransformer</transformer-class-name>
     </divert>
    </diverts>
    

```

  • 실무 적용 시나리오 (프로토콜 어댑터 및 민감 정보 마스킹):
  • 포맷 변환: 신규 모바일 앱(프로듀서)은 모든 데이터를 JSON 포맷으로 쏘지만, 이 데이터를 받아야 하는 구형 메인프레임 컨슈머는 XML 포맷만 이해할 수 있습니다. 클라이언트들을 수정하는 대신, 브로커의 Transformer 클래스 내부에서 JSON 페이로드를 읽어 XML로 파싱한 뒤 대상 주소로 밀어 넣어주는 어댑터(Adapter) 역할을 수행하게 합니다.
  • 데이터 마스킹 (보안): 앞선 Audit Logging 시나리오에서 복제본을 만들 때, 주민등록번호나 신용카드 번호 같은 민감한 데이터가 로그 시스템으로 그대로 흘러가면 안 됩니다. Transformer를 부착하여 복제되는 메시지의 본문에서 민감 정보를 *** 처리(Masking)한 후 Forward Address로 넘기도록 아키텍처를 구성합니다.

4. 아키텍처 설계 시 핵심 고려사항 및 성능 오버헤드

Divert는 매우 편리하지만 브로커의 핵심 리소스를 직접적으로 사용하므로 주의 깊은 설계가 필요합니다.

  1. Transformer 연산 부하: 메시지 본문을 열어서 파싱하고 수정하는 작업(Transformation)은 브로커의 CPU 연산과 JVM 힙 메모리를 막대하게 소모합니다. 초당 수만 건의 대용량 트래픽이 발생하는 주소에 무거운 정규식(Regex) 변환이나 복잡한 JSON-to-XML 파싱 로직을 걸어두면, 브로커 전체의 Throughput이 심각하게 저하됩니다. 가급적 헤더 조작 위주로 사용하고, 무거운 본문 변환은 별도의 전용 Apache Camel 라우터 인스턴스 등으로 분리하는 것이 바람직합니다.
  2. 무한 루프(Infinite Loop) 방지: Divert A가 주소 1에서 주소 2로 라우팅하고, Divert B가 주소 2에서 주소 1로 라우팅하도록 잘못 설정하면, 메시지가 브로커 내부에서 영원히 핑퐁 치며 즉각적인 OOM(Out of Memory)과 서버 셧다운을 유발합니다. 라우팅 토폴로지 구성 시 순환 참조가 발생하지 않도록 철저히 검증해야 합니다.
  3. 트랜잭션 정합성: Non-Exclusive Divert를 통해 복제된 메시지들은 원본 메시지와 동일한 트랜잭션 컨텍스트에 묶이게 됩니다. 만약 프로듀서가 트랜잭션을 롤백하면, 원본 큐뿐만 아니라 Divert로 흘러간 복제 메시지도 함께 롤백되어 데이터의 최종 정합성이 유지됩니다.
반응형