"사용자가 회원 가입을 했습니다. 가입 환영 메일도 보내야 하고, 쿠폰도 지급해야 하고, 통계 로그도 남겨야 합니다."
이때 메시지 큐에 메시지를 하나 던졌을 때, "컨슈머 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처럼 동작하게 만들 수 있어 사실상 업계 표준이 되었습니다.
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
| 스트랭글러 패턴(Strangler Fig Pattern) 완벽 정리 (0) | 2025.12.07 |
|---|---|
| 피처 토글 패턴(Feature Toggle Pattern) 완벽 정리 (0) | 2025.12.07 |
| 이벤트 소싱 패턴(Event Sourcing Pattern) 완벽 정리 (0) | 2025.12.07 |
| 멀티테넌시 패턴(Multi-tenancy Pattern) 완벽 정리 (0) | 2025.12.07 |
| API 버저닝 패턴(API Versioning Pattern) 완벽 정리 (0) | 2025.12.07 |