프로그래밍/디자인패턴

메시징 패턴(Messaging Pattern) 완벽 정리

Jinwookoh 2025. 12. 7. 21:19

"사용자가 회원 가입을 했습니다. 가입 환영 메일도 보내야 하고, 쿠폰도 지급해야 하고, 통계 로그도 남겨야 합니다."

이때 메시지 큐에 메시지를 하나 던졌을 때, "컨슈머 A가 가져가면 컨슈머 B는 못 가져가게 할지", 아니면 **"A도 받고 B도 받게 할지"**가 아키텍처의 핵심입니다.


1. 방식 1: 포인트 투 포인트 (Point-to-Point / Queue) - "선착순 1명"

가장 전통적인 작업 큐(Worker Queue) 방식입니다. 생산자(Producer)가 큐에 메시지를 넣으면, 여러 소비자(Consumer) 중 오직 하나만 메시지를 가져가서 처리합니다.

특징

  • 경쟁적 소비자(Competing Consumers): 소비자들은 메시지를 먼저 가져가기 위해 경쟁합니다. 한 번 소비된 메시지는 큐에서 사라집니다.
  • 부하 분산(Load Balancing): 소비자를 늘리면 처리 속도가 빨라집니다. (N명이 나눠서 처리하니까)

코드 예시 (RabbitMQ Queue / AWS SQS)

Java
 
// 생산자: 큐에 "이미지 리사이징" 작업 등록
queue.send("image-queue", "image_123.jpg");

// 소비자 1
@RabbitListener(queues = "image-queue")
public void worker1(String image) {
    System.out.println("내가 처리함: " + image);
}

// 소비자 2
@RabbitListener(queues = "image-queue")
public void worker2(String image) {
    // 소비자 1이 가져갔으므로, 여기선 실행 안 됨 (일감 나누기)
}

장단점

  • 장점:
    • 작업 분산: 무거운 작업(동영상 인코딩, 이미지 처리)을 여러 서버가 나눠서 처리할 때 최적입니다.
    • 확실한 처리: 메시지가 중복 처리되는 것을 방지합니다.
  • 단점:
    • 확장성 제한: 새로운 기능을 추가하고 싶어서(예: 이미지 처리 후 알림 발송) 새로운 소비자를 붙이면, 기존 소비자의 일감을 뺏어가게 되어 기능이 오작동합니다.

2. 방식 2: 발행-구독 (Publish-Subscribe / Topic) - "동네방네 소문내기"

이벤트 기반 아키텍처(EDA)의 핵심입니다. 생산자(Publisher)가 토픽(Topic)에 메시지를 발행하면, 이를 구독(Subscribe)하고 있는 모든 소비자가 똑같은 메시지를 받습니다.

특징

  • 브로드캐스팅(Broadcasting): 라디오 방송처럼, 주파수(토픽)를 맞춘 모든 사람에게 메시지가 전달됩니다.
  • 느슨한 결합: 생산자는 누가 듣고 있는지 모릅니다. 그냥 외칠 뿐입니다.

코드 예시 (Kafka Topic / AWS SNS)

Java
 
// 생산자: "회원가입 발생!" 이벤트 발행
topic.publish("user-signup-topic", "{userId: 100}");

// 소비자 A (메일 서비스)
@KafkaListener(topics = "user-signup-topic")
public void mailService(String msg) {
    sendWelcomeMail(msg); // 메일 보냄
}

// 소비자 B (쿠폰 서비스)
@KafkaListener(topics = "user-signup-topic")
public void couponService(String msg) {
    giveCoupon(msg); // 쿠폰 줌 (A와 동시에 실행됨)
}

장단점

  • 장점:
    • 높은 확장성: "통계 기능도 추가해 줘"라는 요청이 오면, 기존 코드를 건드릴 필요 없이 '통계 소비자'만 하나 더 띄워서 토픽을 구독하면 됩니다. (OCP 준수)
  • 단점:
    • 부하 분산의 복잡함: 한 토픽의 메시지를 여러 서버가 나눠서 처리하려면(스케일 아웃), Kafka의 경우 파티션(Partition)과 컨슈머 그룹(Consumer Group) 개념을 잘 이해하고 설계해야 합니다.

3. 실무 비교: 언제 무엇을 쓰는가?

구분 Point-to-Point (Queue) Publish-Subscribe (Topic)
수신자 수 1명 (1:1) N명 (1:N)
주요 목적 일감 나누기 (Load Balancing) 이벤트 전파 (Notification)
소비자 추가 시 기존 소비자의 처리량이 줄어듦 (속도 향상) 새로운 기능이 추가됨 (기능 확장)
대표 기술 RabbitMQ Queue, AWS SQS, ActiveMQ Kafka Topic, AWS SNS, Redis Pub/Sub
추천 상황 무거운 배치 작업, 1:1 비동기 명령 처리 회원 가입 후처리, 데이터 변경 감지(CDC), 알림 시스템

결론

"이 작업은 무거우니까 여러 서버가 나눠서 빨리 처리해야 해"라면 포인트 투 포인트(Queue) 패턴이 정답입니다.

하지만 "이 사건이 발생하면 메일도 보내고, 카톡도 보내고, 로그도 쌓아야 해"처럼 하나의 사건이 여러 후속 조치를 유발한다면 발행-구독(Pub/Sub) 패턴을 사용해야 시스템 간 결합도를 낮추고 유연하게 확장할 수 있습니다.

Tip: Kafka는 '컨슈머 그룹' 기능을 이용해 Pub/Sub 방식이면서도 그룹 내에서는 Queue처럼 동작하게 만들 수 있어 사실상 업계 표준이 되었습니다.