Spring 7기 프로젝트/모임 플렛폼 프로젝트

Spring Boot에서 RabbitMQ Publisher Confirm 도메인별 설정하기

JuNo_12 2025. 8. 6. 16:55

들어가며

Spring Boot에서 RabbitMQ를 사용할 때, 메시지 발행의 신뢰성을 보장하기 위해 Publisher Confirm 기능을 활용할 수 있습니다. 이번 글에서는 도메인 분리 아키텍처에서 각 도메인별로 독립적인 Publisher Confirm 설정을 구현하는 과정을 공유합니다.


Publisher Confirm이란?

일반적으로 RabbitMQ에 메시지를 발송할 때는 다음과 같은 코드를 작성합니다:

rabbitTemplate.convertAndSend(exchange, routingKey, message);
// 메시지를 보냈는데, 정말 도착했을까요?

Publisher Confirm은 RabbitMQ 브로커가 메시지를 성공적으로 받았는지 확인해주는 기능입니다. 이를 통해 메시지 발행의 신뢰성을 크게 향상시킬 수 있습니다.

Publisher Confirm의 주요 기능

  1. 메시지 발행 성공/실패 확인: 브로커가 메시지 수신 여부를 명시적으로 응답
  2. Publisher Returns: 라우팅 실패 시 메시지 반환 및 알림
  3. 상관관계 ID: 각 메시지별로 고유 ID를 통한 추적

프로젝트 구조

본 프로젝트는 도메인 분리 아키텍처를 채택하고 있으며, 각 도메인별로 독립적인 RabbitMQ 설정을 가지고 있습니다:

├── global/rabbitmq/config/
│   └── RabbitMQConfig.java          # 공통 설정
├── domain/user/event/rabbitmq/
│   ├── config/
│   │   ├── UserExchangeConfig.java  # Exchange 정의
│   │   └── UserRabbitMQConfig.java  # ConnectionFactory + RabbitTemplate
│   └── producer/
│       └── UserEventPublisher.java  # 이벤트 발행
└── domain/payment/infra/rabbitmq/   # Payment 도메인도 동일한 구조

구현 과정

1. Exchange 설정

먼저 User 도메인 전용 Exchange를 정의합니다:

 

2. ConnectionFactory 설정의 문제점과 해결

초기에는 새로운 ConnectionFactory를 생성하여 설정하려고 했습니다:

// 문제가 있던 초기 구현
@Bean("userConnectionFactory")
public ConnectionFactory userConnectionFactory() {
    CachingConnectionFactory factory = new CachingConnectionFactory();
    
    // 문제: 연결 정보(host, username, password)가 설정되지 않음
    factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
    factory.setPublisherReturns(true);
    
    return factory;
}

이 방식의 문제점:

  • RabbitMQ 연결 정보가 설정되지 않아 기본값(guest/guest)이 사용됨
  • 환경변수로 설정한 사용자 정보가 반영되지 않음

3. 해결책: 기본 ConnectionFactory 활용

기본 ConnectionFactory의 설정을 상속받아 Publisher Confirm 기능만 추가하는 방식으로 해결했습니다:

 

4. RabbitTemplate 설정

Publisher Confirm이 활성화된 전용 RabbitTemplate을 구성합니다:

 

5. EventPublisher 구현

전용 RabbitTemplate을 사용하는 이벤트 발행자를 구현합니다:


트러블슈팅

문제 1: ConfigurationProperties 중복 사용

처음에는 @ConfigurationProperties(prefix = "spring.rabbitmq")를 사용하려 했으나, 이미 글로벌 설정에서 사용하고 있어 "Duplicated prefix" 오류가 발생했습니다.

해결: 기본 ConnectionFactory를 상속받는 방식으로 변경하여 중복 문제를 해결했습니다.

 

문제 2: 인증 정보 미반영

환경변수로 설정한 RabbitMQ 인증 정보가 User 도메인 ConnectionFactory에 반영되지 않아, 기본값인 guest 계정으로 연결을 시도하는 문제가 있었습니다.

해결: 기본 ConnectionFactory의 getRabbitConnectionFactory()를 통해 연결 정보를 상속받도록 구현했습니다.


검증 방법

구현된 Publisher Confirm이 정상 작동하는지 확인하는 방법입니다:

1. 성공 케이스 테스트

[User] 이벤트 발행 요청 완료 - eventType: USER_WITHDRAWN, correlationId: user-withdrawn-123
[User] 메시지 발행 성공 - correlationData: user-withdrawn-123

 

2. 실패 케이스 테스트

RabbitMQ 서버를 중단한 후 메시지 발행 시:

[User] 메시지 발행 실패 - correlationData: user-withdrawn-123, cause: Connection refused
[User] 이벤트 발행 실패 - eventType: USER_WITHDRAWN, error: Connection refused

 

장점

이번 구현의 주요 장점들입니다:

  1. 신뢰성 향상: 메시지 발행 성공/실패를 명확히 추적할 수 있습니다.
  2. 도메인 분리: 각 도메인이 독립적인 RabbitMQ 설정을 가집니다.
  3. 설정 재사용: 기본 ConnectionFactory의 설정을 상속받아 중복을 최소화합니다.
  4. 확장성: 새로운 도메인 추가 시 동일한 패턴을 적용할 수 있습니다.

결론

Spring Boot에서 도메인별 RabbitMQ Publisher Confirm 설정을 구현하면서, 설정 상속과 Bean 주입 방식의 중요성을 깨달았습니다. 특히 기존 설정을 재사용하면서 필요한 기능만 추가하는 방식은 코드의 중복을 줄이고 유지보수성을 크게 향상시킵니다.

이러한 패턴은 다른 인프라 컴포넌트 설정에도 응용할 수 있으며, 마이크로서비스나 도메인 분리 아키텍처에서 특히 유용합니다.