학습목표
- 비동기 메시징 시스템을 종류와 그 예시 들을 이해한다
목차
- 비동기 메시징 시스템
- 비동기 메시징 시스템 종류
- 비동기 메시징 시스템 기술
- 비동기 메시징 선택시 고려사항
- 비동기 메시징 시스템의 주요패턴
들어가기 전..
비동기 시스템의 등장과 아키텍쳐 복습하기
[대규모트래픽 이론] #2.1 비동기 처리 아키텍처 이해와 확장
학습목표비동기 처리시스템의 아키텍쳐를 이해한다목차비동기 처리 아키텍쳐 이해와 확장비동기 메시징 시스템 이해비동기 처리 시스템 장단점 및 사례들어가기 전..동시성, 비동기 개념 복습
dev-rosiepoise.tistory.com
1. 비동기 메시징 시스템이란?
프로듀서(Producer)와 컨슈머(Consumer)가 독립적으로 동작하며, 서로 직접적으로 데이터를 주고받지 않고 메시지 큐나 이벤트 버스와 같은 중간 매체를 통해 통신하는 시스템
비동기 메시징 시스템의 필요성
- 대규모 시스템에서는 매 순간 수 많은 요청이 동시에 들어오며, 이를 모두 동기적으로 처리하게 되면 시스템에 과부하가 발생할 가능성
- 이때 비동기 메시징 시스템은 트래픽을 효율적으로 분산하고, 확장성을 보장하는데 중요한 역할
- 주요 목적은 시스템간 느슨합 결합과 작업의 병렬 처리를 통해 효율성을 극대화
2. 비동기 메시징 시스템의 종류
a) 이벤트 버스
- 이벤트 버스는 시스템 내에서 발생하는 이벤트를 전달하는 비동기 메시징 시스템
- 이벤트는 시스템의 상태 변화나 사용자 액션에 의해 발생하며, 이를 처리하기 위해 비동기적으로 여러 서비스 간에 전달
- 서비스간 실시간으로 데이터를 주고받을 수 있어, 빠르게 상태 변화에 반응
- 이벤트 구독서비스를 쉽게 추가함으로써, 각 서비스를 독립적으로 실행이 가능토록하고 시스템간 확장성에 용이
- 이벤트 버스의 동작원리
- Event Producer : 이벤트를 발생시키는 주체
- Event Bus : 이벤트를 구독하고 있는 여러 서비스로 전달하는 역할
- Event Consumer : 이벤트를 구독하고 있는 서비스
- ex) 주문서비스 - 1.결제, 2.배송 등
b) 메시지 큐 (Message Queue)
- 메시지 큐는 프로듀서가 생성한 메시지를 큐에 넣고, 이를 소비자가 준비된 후에 처리하는 구조
- 순간적으로 트래픽이 몰리더라도, 순차적 처리가 가능하며 소비자의 수를 늘리면 더 빠른 처리가 가능함.
- 트래픽 증가에 유연한 대처
- 이 방식은 서비스 간 느슨한 결합을 가능하게 하고, 확장성을 높이는데 유용
- 메시지 큐의 동작원리
- Producer : 메시지를 생성하여 큐에 넣는 주체
- Queue : 메시지가 일시적으로 저장되는 공간
- Consumer : 큐에서 메시지를 가져가 처리하는 주체
c) 메시지 브로커 (Message Broker)
- 메시지 브로커는 메시지 큐나 이벤트 버스와 비슷한 개념이지만, 더 큰 범위에서 시스템 간 통신을 중개하는 역할
- 메시지 브로커는 서로 다른 어플리케이션이나 시스템 간에 비동기 메시지를 전달
- RabbitMQ, Kafka와 같은 도구가 여기에 해당
- 브로커의 주요 역할
- 메시징 저장 : 메시지를 큐에 저장하여, 시스템이 메시지를 손실하지 않고 안정적으로 전달
- 장애 발생시, 메시지를 읽지 않고 시스템 복구시 메시지를 다시 처리
- 트래픽 분산 : 브로커는 트래픽을 효율적으로 분산시켜 시스템에 과부하가 발생하지 않도록 도와줌
- 소비자 수를 늘려, 빠른 처리를 가능하게 함
- 서비스간 중재 : 서로 다른 시스템 간의 메시지를 중개하여, 각 시스템이 독립적으로 동작할 수 있도록 함
- 메시징 저장 : 메시지를 큐에 저장하여, 시스템이 메시지를 손실하지 않고 안정적으로 전달
2.1 Message Queue vs Message Broker
메시지 큐 | 메시지 브로커 |
단순 메세지 저장소로써, 생산자와 소비자 간의 메시지 임시 저장을 담당 | 메시지 흐름을 중개하고 라우팅을 담당 |
FIFO(선입선출)방식으로 메시지를 처리 | 다양한 전달 패턴을 지원(Publish/Subscribe) |
단일 큐에 메시지를 저장하고 순차적으로 처리 | 메시지를 여러 수신자에게 동시 전달 가능 |
주로 일시적 저장과 처리 대기 역할 | 메시지의 전달 보장, 확장성, 변환 등을 관리 |
RabbitMQ, Amazon SQS 같은 시스템에서 큐로 사용 | Kafka, RabbitMQ(브로커 역할 포함) 등에서 중개 역할 |
3. 비동기 메시징 시스템의 기술
3.1 메시지 큐 기반
a) RabbitMQ


- 큐 기반 구조 : 프로듀서가 메시지를 큐에 넣고, 컨슈머가 그 큐에서 메시지를 가져가 처리하는 방식. 이는 메시지를 비동기적으로 처리하는데 적합
- 메시징 라우팅 : RabbitMQ는 메시지 라우팅 옵션을 제공하며, direct exchange, fanout exchange, topic exchange 등을 통해 특정 조건에 맞는 메지시를 큐로 전달
- 스케쥴링 및 우선 순위 메시징 : RabbitMQ는 메시지에 우선순위(priority)를 설정할 수 있으며, 메시지의 스케쥴링도 지원
- 내구성 있는 메시지 저장 : 메시지를 디스크에 젖아하여 시스템 장애 발생 시에도 메시지 손실을 방지
- 확장성 : 클러스트링을 통해 RabbitMQ를 확장할 수 있으며, 분산 처리 환경에서 높은 가용성을 제공
b) Amazon SQS (Simple Que Service)
- 완전 관리형 서비스 : aws가 시스템을 관리, 사용자는 인프라를 신경 쓰지 않고 서비스 구축에 집중
- 자동 확장 : amazon sqs는 트래픽의 변화에 따라 자동으로 확장, 대규모 메시지 트래픽을 처리할 때 추가적인 설정없이 시스템을 자동으로 대응
- 메시지 전달 보장 : 최소 한 번 메시지를 전달하는 at least once 방식이 기본으로 제공되며, fifo 큐를 선택하면 메시지 순서를 보장
- 지연 큐 : amazon sqs는 메시지를 일정 시간 동안 대기시킨 후 처리할 수 있는 지연 큐 기능을 제공, 이 기능은 특정 조건에서 메시지를 지연 처리해야할 때 유용
- 비용 효율성 : 클라우드 기반 서비스로, 사용한 만큼만 비용 지불
3.2 메시지 브로커 기반
a) Apache Kafka 아파치 카프카

- 분산처리 : 카프카는 클러스터로 구성되어 대규모 데이터를 분산처리하며, 수평적으로 확장가능
- 높은 처리량과 지연 시간 최소화 : 고속의 데이터 처리량을 제공하며, 실시간 데이터 스트리밍 처리에서 매우 적합
- 토픽 기반 구조 : 데이터를 토픽으로 관리. 프로듀서가 메시지를 특정 토픽에 게시하면, 이를 구독한 여러 소비자가 동시에 데이터를 처리 가능
- 순서 보장 : 각 파티션 내에서 메시지의 순서를 보장하며, 메시지의 손실 없이 내구성을 보장하는 로그 저장 방식을 채택
- 내구성 보장 : 데이터를 디스크에 저장하며, 메시지의 손실을 방지하기 위해 복제 지원
4. 메시징 시스템 선택 시 고려사항
- 확장성
- 시스템 부하가 늘어났을 때 대응할 수 있는 능력
- 사용 사례에 맞는 기능
- 각 메시징 시스템은 고유의 기능을 제공
- RabbitMQ는 메시지 라우팅 기능이 뛰어남
- kafka는 로그 기반의 메시징 처리에 최적화
- amazon sqs는 손쉬운 클라우드 관리형 서비스를 제공
5. 비동기 메시징 시스템의 주요 패턴
a) Event-Driven Architecture

- 이벤트 기반 아키텍처는 시스템의 각 구성 요소들이 특정 이벤트에 반응하여 작업을 처리하는 방식
- 이벤트가 발생하면 이를 다른 서비스나 모듈이 구독하고, 이벤트가 도착하면 해당 작업을 비동기적으로 처리하는 구조
- 구성요소
- Event Producer : 이벤트를 발생시키는 주체
- Event Consumer : 이벤트를 구독하고 이를 처리하는 주체
b) CQRS (Command Query Responsibility Segregation)

- 명령(Command)과 조회(Query)를 분리하여 각각 독립적으로 처리하는 아키텍쳐 패턴
- 명령은 데이터를 변경하는 작업을 의미하며, 조회는 데이터를 읽는 작업을 의미
- 구성요소
- Command Handlers : 데이터를 변경하는 작업을 처리, 이때 메시지큐를 사용해 명령이 큐에 저장되고, 비동기적으로 처리
- Query Handlers: 데이터를 조회하는 작업을 처리, 데이터 조회는 즉각적으로 처리될 수 있지만, 명령은 비동기적으로 처리되어 데이터 일관성을 유지
- Event Sourcing : 모든 상태 변경을 이벤트로 기록하고, 이벤트를 통해 시스템의 상태를 재구성하는 방식
c) 사가 패턴 (Saga Pattern)

- 분산 트랜잭션을 처리할 때 사용되는 아키텍쳐 패턴으로, 각 서비스에서 독립적으로 트랜잭션을 처리하지만, 전체 프로세스는 논리적으로 하나의 트랜잭션처럼 보이게 함
- 사가 패턴은 각 서비스에서 처리된 결과를 비동기적으로 전달받아 트랜잭션을 완성하거나 실패했을 경우 보상 작업을 수행
- 구성요소
- Saga Coordinator : 트랜잭션의 시작과 종료를 관리하며, 중간에 트랜잭션에 실패할 경우 보상 작업을 실행
- Local Transactions : 각 서비스에서 실행되는 독립적인 트랜잭션으로 각 서비스는 메시지 큐를 통해 비동기적으로 트랜잭션 결과를 전달
d) 백프레셔 패턴 (Backpressure Pattern)
- 시스템이 과부하 상태일 때 요청을 거부하거나 처리 속도를 늦추는 방식으로 트래픽을 조절하는 아키텍쳐 패턴
- 비동기 메시징 시스템과 함께 사용되며, 대규모 트래픽 상황에서 시스템의 안정성을 보장하는 데 도움
- 구성요소
- Producer : 메시지를 생성하여 큐에 넣는 역할을 하디만, 큐가 가득 차면 백프레셔를 통해 메시지 생산을 중단하거나 속도를 늦춤
- Consumer: 메시지를 처리하는 소비자로서, 큐에서 처리할 수 있는 메시지의 양을 제어하여 시스템과부하를 방지
e) Durable Messaging Pattern
- 메시지를 손실 없이 처리할 수 있도록 보장하는 패턴
- 메시지가 중간에 손실되거나 누락되지 않도록 메시지를 저장하고, 시스템 장애 시에도 복구가 가능한 상태로 유지
- 구성요소
- Persistent Queue : 메시지가 시스템에 도착하면 큐에 영구적으로 저장, 메시지는 실패 시 재시도될 수 있으며, 시스템이 복구된 후에도 메시지가 손실되지 않음
- Retry Mechanism : 실패한 메시지를 재처리할 수 있는 메커니즘을 포함하여, 메시지가 손실도지 않도록 보장
tmi 1
이벤트 버스랑 메시지 브로커랑 개념이 너무 비슷한데 왜 따로 나눠쓰는지 정확하게 이해가 안가서 예시를 짚고가고자 질문을 함
GPT: 와우… 이제 진짜 핵심 질문 나왔네요! 🔥
"이벤트 버스(Event Bus)와 메시지 브로커(Message Broker)는 같은 개념인가?"
→ 얼핏 보면 비슷해 보이지만, 완전히 같지는 않습니다!
둘은 비슷한 역할을 하지만, 의도와 사용 방식, 스코프가 다릅니다.
이벤트 버스 | 메세지 브로커 | |
개념 | 내부 시스템 간 이벤트 전달 | 독립 서비스 간 메시지 전달 |
역할 | 컴포넌트 간 느슨한 연결 | 시스템 간 안정적 메시지 교환 |
범위 | 애플리케이션 내부 또는 모놀리식 구조 | 마이크로서비스 간 or 시스템 간 |
전송 방식 | 대부분 메모리 기반, 경량 | 디스크 기반, 네트워크 기반 |
기술 예시 | Spring Event, Guava EventBus, NestJS EventEmitter | Kafka, RabbitMQ, ActiveMQ, Amazon SQS |
확장성 | 제한적 (단일 프로세스 중심) | 고성능, 대규모 확장 지원 |
전송 신뢰성 | 낮거나 없음 (기본적으로 fire-and-forget) | 매우 높음 (ack, retry, durable queue 등) |
🔹 이벤트 버스(Event Bus)
- 목적: 내부 객체나 컴포넌트들끼리 메시지(이벤트)를 주고받도록 하는 패턴
- 일반적으로 싱글 프로세스 환경에서 경량으로 동작
- 대표 사례:
- Spring ApplicationEventPublisher
- Google Guava EventBus
- NestJS의 EventEmitter
🧠 "한 애플리케이션 내부에서 A → B → C 흐름을 느슨하게 연결하고 싶을 때" 사용
🔹 메시지 브로커(Message Broker)
- 목적: 서로 다른 시스템 간에 메시지를 안정적으로 전달하는 인프라 컴포넌트
- 대부분 네트워크 기반, 디스크 저장 및 재시도, 장애 복구 기능 포함
- 대표 사례:
- Apache Kafka
- RabbitMQ
- Amazon SNS/SQS
- Google Pub/Sub
🧠 "마이크로서비스 간 통신"이나 "이벤트 중심의 확장성 있는 구조"에서 사용
그래서 결론은?
🔸 같은 개념은 아니고,
🔹 기능은 일부 겹치지만, 사용 목적과 범위가 다르다!
- 이벤트 버스는 애플리케이션 내부 이벤트 통신
- 메시지 브로커는 시스템 간/서비스 간 메시지 교환
🎯 용도에 따른 정리
앱 내부에서 컴포넌트 간 통신 | ✅ 이벤트 버스 |
마이크로서비스 간 이벤트 통신 | ✅ 메시지 브로커 |
네트워크 기반, 확장 가능한 구조 | ✅ 메시지 브로커 |
가볍고 빠른 로컬 이벤트 전달 | ✅ 이벤트 버스 |
tmi 2
위의 차이를 이해하게됨, 근데 왜 강의에서는 이벤트 버스 예를 주문 - 결제, 배송으로 들었는지 궁금함
GPT:
지금 말하신 부분은 실무에서도 많이들 혼동하는 포인트예요.
"이벤트 버스는 내부용이라면서, 왜 주문-결제-배송 간 이벤트 통신에 쓴다고 하지?"
→ 이건 정확히 어떤 ‘규모’와 ‘경계’를 말하느냐에 따라 완전히 달라져요.
✅ 핵심 정리 먼저!
이벤트 버스는 일반적으로 ‘하나의 애플리케이션 내부 컴포넌트 간 통신’에 사용하는 것이 맞습니다.
그런데, 서비스가 모두 한 애플리케이션 안에 있을 경우, 주문-결제-배송을 이벤트 버스로 연결할 수도 있어요.
하지만 마이크로서비스처럼 각각이 독립된 배포 단위일 경우는 메시지 브로커를 써야 합니다.
🔹 [예제 1] 작은 규모 / 단일 애플리케이션 기반
✨ Spring Boot 하나에 주문, 결제, 배송 모듈이 모두 존재
📦 구조 예시:
- OrderService
- PaymentService
- ShippingService
🧠 이 경우:
- 모든 서비스는 같은 JVM 내에서 실행
- 동기 호출보다 느슨한 연결이 필요함
- 따라서 Spring의 ApplicationEventPublisher 같은 이벤트 버스 패턴 사용 가능!
// 주문 완료 → 이벤트 발행
publisher.publishEvent(new OrderCreatedEvent(order));
// 결제 모듈이 이벤트 수신
@EventListener
public void handle(OrderCreatedEvent event) {
paymentService.pay(event.getOrder());
}
🔹 [예제 2] 대규모 마이크로서비스 아키텍처
✨ 주문, 결제, 배송이 각각 독립된 서비스로 운영되는 경우
📦 구조 예시:
- order-service (Spring Boot App)
- payment-service (Spring Boot App)
- shipping-service (Spring Boot App)
🧠 이 경우:
- 서로 다른 서비스는 네트워크를 통해 통신해야 함
- 한 서비스의 이벤트를 다른 서비스에 비동기 전파해야 함
- 이때는 Kafka / RabbitMQ 같은 메시지 브로커 사용이 필수
// order-service
kafkaTemplate.send("order.created", orderEvent);
// payment-service
@KafkaListener(topics = "order.created")
public void onOrderCreated(OrderCreatedEvent event) {
paymentService.pay(event);
}
📌 실무에서의 쓰임 요약
사용처 | 이벤트 버스 | 메시지 브로커 |
모놀리식(Spring 내부 모듈) | ✅ 적합 | ❌ 과함 |
마이크로서비스 (다른 서비스 간) | ❌ 불가 | ✅ 필수 |
빠르게 처리하고 싶을 때 | ✅ 메모리 기반이라 빠름 | ✅ 튼튼하지만 약간 느림 |
복구, 재시도 필요 | ❌ 기능 없음 | ✅ 기능 풍부 |
tmi 3
위 답변을 이해하고, 그럼 실제로 어떤 경우 이벤트버스를 사용하는지 궁금해졌음
그럼 이벤트 버스는 어떤 컴포넌트 간 느슨한 결합시에 쓰는거야? 주문시스템 그런거 말구 ?
gpt :
"이벤트 버스는 언제 쓰는 거야? 주문 시스템 같은 도메인 말고, 어떤 컴포넌트들 사이에서 느슨하게 결합시키는 데 쓰이는 거야?"
→ 이 질문 진짜 잘 하셨어요.
‘도메인 레벨 이벤트’가 아니라, 기술적/아키텍처적 컴포넌트 사이 연결용으로 이벤트 버스를 쓰는 경우가 많거든요.
✅ 이벤트 버스는 이런 상황에서 사용해요
🎯 비즈니스 흐름이 직접적이지 않지만, 어떤 작업이 끝났을 때 “누군가 반응해야 하는” 경우
🔹 1. 파일 업로드 후 후속 작업
- 파일 업로드 완료 → 썸네일 생성
- 파일 업로드 완료 → DB 기록 로그
- 파일 업로드 완료 → Slack 알림
🧠 업로더 컴포넌트는 "썸네일 생성자"가 있는지도 모르고 그냥 이벤트만 던짐
→ FileUploadedEvent 전파
🔹 2. 사용자 회원가입 이후 후속 처리
- 유저 가입 완료 → 이메일 발송
- 유저 가입 완료 → 추천인 포인트 적립
- 유저 가입 완료 → 마케팅 푸시 등록
🧠 UserService는 후속 동작을 신경 쓰지 않음
→ UserRegisteredEvent 발행 → 여러 리스너가 반응
🔹 3. 관리자 설정 변경 시 여러 모듈에 반영
- 관리자 UI에서 설정 변경 → 캐시 무효화
- 관리자 설정 변경 → 감사 로그 기록
- 관리자 설정 변경 → 시스템 전반에 브로드캐스트
🧠 AdminSettingService는 구체적인 반응을 몰라도 됨
→ ConfigChangedEvent 전파
🔹 4. 애플리케이션 부팅 이벤트 처리
- Spring Boot 실행 완료 후 초기화
- DB 초기 로딩
- 외부 API 호출 준비
🧠 ApplicationReadyEvent 사용
@EventListener(ApplicationReadyEvent.class)
public void onStart() {
System.out.println("앱 시작 시 초기화 수행!");
}
🔹 5. 도메인 외 관찰성, 모니터링, 감사 로그 처리
- 주문 생성 시 → AuditLogService가 로그 남김
- 결제 성공 시 → MonitoringService가 메트릭 기록
🧠 비즈니스 흐름에는 영향 없음
→ 하지만 리스너를 통해 부가 기능 연결
네.. 오늘도 챗과장님이 궁금증 해소 마무리 시켜주셨뜸 감사여!
참고, 강의 및 구글링
1티어 패션 커머스의 세일 도메인 프로젝트로 배우는 대규모 트래픽을 견디는 실전 백엔드의 모
실전 대용량 트래픽 처리의 모든 것! 대규모 시스템 설계부터 기능 구현, 테스트까지!
fastcampus.co.kr
'대용량 시스템 > 대규모 트래픽 이론' 카테고리의 다른 글
[대규모트래픽 이론] #3.1 대규모 트래픽 처리 개요 (0) | 2025.04.06 |
---|---|
[대규모트래픽 이론] #2.3 비동기 처리 시스템의 장단점 및 사례 (0) | 2025.04.06 |
[대규모트래픽 이론] #2.1 비동기 처리 아키텍처 이해와 확장 (0) | 2025.03.29 |
[대규모트래픽 이론] #1.2 동시성 처리와 비동기 처리의 기본 구조 (0) | 2025.03.29 |
[대규모트래픽 이론] #1.1 동시성 처리와 비동기 처리의 기본 개념 (0) | 2025.03.11 |
학습목표
- 비동기 메시징 시스템을 종류와 그 예시 들을 이해한다
목차
- 비동기 메시징 시스템
- 비동기 메시징 시스템 종류
- 비동기 메시징 시스템 기술
- 비동기 메시징 선택시 고려사항
- 비동기 메시징 시스템의 주요패턴
들어가기 전..
비동기 시스템의 등장과 아키텍쳐 복습하기
[대규모트래픽 이론] #2.1 비동기 처리 아키텍처 이해와 확장
학습목표비동기 처리시스템의 아키텍쳐를 이해한다목차비동기 처리 아키텍쳐 이해와 확장비동기 메시징 시스템 이해비동기 처리 시스템 장단점 및 사례들어가기 전..동시성, 비동기 개념 복습
dev-rosiepoise.tistory.com
1. 비동기 메시징 시스템이란?
프로듀서(Producer)와 컨슈머(Consumer)가 독립적으로 동작하며, 서로 직접적으로 데이터를 주고받지 않고 메시지 큐나 이벤트 버스와 같은 중간 매체를 통해 통신하는 시스템
비동기 메시징 시스템의 필요성
- 대규모 시스템에서는 매 순간 수 많은 요청이 동시에 들어오며, 이를 모두 동기적으로 처리하게 되면 시스템에 과부하가 발생할 가능성
- 이때 비동기 메시징 시스템은 트래픽을 효율적으로 분산하고, 확장성을 보장하는데 중요한 역할
- 주요 목적은 시스템간 느슨합 결합과 작업의 병렬 처리를 통해 효율성을 극대화
2. 비동기 메시징 시스템의 종류
a) 이벤트 버스
- 이벤트 버스는 시스템 내에서 발생하는 이벤트를 전달하는 비동기 메시징 시스템
- 이벤트는 시스템의 상태 변화나 사용자 액션에 의해 발생하며, 이를 처리하기 위해 비동기적으로 여러 서비스 간에 전달
- 서비스간 실시간으로 데이터를 주고받을 수 있어, 빠르게 상태 변화에 반응
- 이벤트 구독서비스를 쉽게 추가함으로써, 각 서비스를 독립적으로 실행이 가능토록하고 시스템간 확장성에 용이
- 이벤트 버스의 동작원리
- Event Producer : 이벤트를 발생시키는 주체
- Event Bus : 이벤트를 구독하고 있는 여러 서비스로 전달하는 역할
- Event Consumer : 이벤트를 구독하고 있는 서비스
- ex) 주문서비스 - 1.결제, 2.배송 등
b) 메시지 큐 (Message Queue)
- 메시지 큐는 프로듀서가 생성한 메시지를 큐에 넣고, 이를 소비자가 준비된 후에 처리하는 구조
- 순간적으로 트래픽이 몰리더라도, 순차적 처리가 가능하며 소비자의 수를 늘리면 더 빠른 처리가 가능함.
- 트래픽 증가에 유연한 대처
- 이 방식은 서비스 간 느슨한 결합을 가능하게 하고, 확장성을 높이는데 유용
- 메시지 큐의 동작원리
- Producer : 메시지를 생성하여 큐에 넣는 주체
- Queue : 메시지가 일시적으로 저장되는 공간
- Consumer : 큐에서 메시지를 가져가 처리하는 주체
c) 메시지 브로커 (Message Broker)
- 메시지 브로커는 메시지 큐나 이벤트 버스와 비슷한 개념이지만, 더 큰 범위에서 시스템 간 통신을 중개하는 역할
- 메시지 브로커는 서로 다른 어플리케이션이나 시스템 간에 비동기 메시지를 전달
- RabbitMQ, Kafka와 같은 도구가 여기에 해당
- 브로커의 주요 역할
- 메시징 저장 : 메시지를 큐에 저장하여, 시스템이 메시지를 손실하지 않고 안정적으로 전달
- 장애 발생시, 메시지를 읽지 않고 시스템 복구시 메시지를 다시 처리
- 트래픽 분산 : 브로커는 트래픽을 효율적으로 분산시켜 시스템에 과부하가 발생하지 않도록 도와줌
- 소비자 수를 늘려, 빠른 처리를 가능하게 함
- 서비스간 중재 : 서로 다른 시스템 간의 메시지를 중개하여, 각 시스템이 독립적으로 동작할 수 있도록 함
- 메시징 저장 : 메시지를 큐에 저장하여, 시스템이 메시지를 손실하지 않고 안정적으로 전달
2.1 Message Queue vs Message Broker
메시지 큐 | 메시지 브로커 |
단순 메세지 저장소로써, 생산자와 소비자 간의 메시지 임시 저장을 담당 | 메시지 흐름을 중개하고 라우팅을 담당 |
FIFO(선입선출)방식으로 메시지를 처리 | 다양한 전달 패턴을 지원(Publish/Subscribe) |
단일 큐에 메시지를 저장하고 순차적으로 처리 | 메시지를 여러 수신자에게 동시 전달 가능 |
주로 일시적 저장과 처리 대기 역할 | 메시지의 전달 보장, 확장성, 변환 등을 관리 |
RabbitMQ, Amazon SQS 같은 시스템에서 큐로 사용 | Kafka, RabbitMQ(브로커 역할 포함) 등에서 중개 역할 |
3. 비동기 메시징 시스템의 기술
3.1 메시지 큐 기반
a) RabbitMQ


- 큐 기반 구조 : 프로듀서가 메시지를 큐에 넣고, 컨슈머가 그 큐에서 메시지를 가져가 처리하는 방식. 이는 메시지를 비동기적으로 처리하는데 적합
- 메시징 라우팅 : RabbitMQ는 메시지 라우팅 옵션을 제공하며, direct exchange, fanout exchange, topic exchange 등을 통해 특정 조건에 맞는 메지시를 큐로 전달
- 스케쥴링 및 우선 순위 메시징 : RabbitMQ는 메시지에 우선순위(priority)를 설정할 수 있으며, 메시지의 스케쥴링도 지원
- 내구성 있는 메시지 저장 : 메시지를 디스크에 젖아하여 시스템 장애 발생 시에도 메시지 손실을 방지
- 확장성 : 클러스트링을 통해 RabbitMQ를 확장할 수 있으며, 분산 처리 환경에서 높은 가용성을 제공
b) Amazon SQS (Simple Que Service)
- 완전 관리형 서비스 : aws가 시스템을 관리, 사용자는 인프라를 신경 쓰지 않고 서비스 구축에 집중
- 자동 확장 : amazon sqs는 트래픽의 변화에 따라 자동으로 확장, 대규모 메시지 트래픽을 처리할 때 추가적인 설정없이 시스템을 자동으로 대응
- 메시지 전달 보장 : 최소 한 번 메시지를 전달하는 at least once 방식이 기본으로 제공되며, fifo 큐를 선택하면 메시지 순서를 보장
- 지연 큐 : amazon sqs는 메시지를 일정 시간 동안 대기시킨 후 처리할 수 있는 지연 큐 기능을 제공, 이 기능은 특정 조건에서 메시지를 지연 처리해야할 때 유용
- 비용 효율성 : 클라우드 기반 서비스로, 사용한 만큼만 비용 지불
3.2 메시지 브로커 기반
a) Apache Kafka 아파치 카프카

- 분산처리 : 카프카는 클러스터로 구성되어 대규모 데이터를 분산처리하며, 수평적으로 확장가능
- 높은 처리량과 지연 시간 최소화 : 고속의 데이터 처리량을 제공하며, 실시간 데이터 스트리밍 처리에서 매우 적합
- 토픽 기반 구조 : 데이터를 토픽으로 관리. 프로듀서가 메시지를 특정 토픽에 게시하면, 이를 구독한 여러 소비자가 동시에 데이터를 처리 가능
- 순서 보장 : 각 파티션 내에서 메시지의 순서를 보장하며, 메시지의 손실 없이 내구성을 보장하는 로그 저장 방식을 채택
- 내구성 보장 : 데이터를 디스크에 저장하며, 메시지의 손실을 방지하기 위해 복제 지원
4. 메시징 시스템 선택 시 고려사항
- 확장성
- 시스템 부하가 늘어났을 때 대응할 수 있는 능력
- 사용 사례에 맞는 기능
- 각 메시징 시스템은 고유의 기능을 제공
- RabbitMQ는 메시지 라우팅 기능이 뛰어남
- kafka는 로그 기반의 메시징 처리에 최적화
- amazon sqs는 손쉬운 클라우드 관리형 서비스를 제공
5. 비동기 메시징 시스템의 주요 패턴
a) Event-Driven Architecture

- 이벤트 기반 아키텍처는 시스템의 각 구성 요소들이 특정 이벤트에 반응하여 작업을 처리하는 방식
- 이벤트가 발생하면 이를 다른 서비스나 모듈이 구독하고, 이벤트가 도착하면 해당 작업을 비동기적으로 처리하는 구조
- 구성요소
- Event Producer : 이벤트를 발생시키는 주체
- Event Consumer : 이벤트를 구독하고 이를 처리하는 주체
b) CQRS (Command Query Responsibility Segregation)

- 명령(Command)과 조회(Query)를 분리하여 각각 독립적으로 처리하는 아키텍쳐 패턴
- 명령은 데이터를 변경하는 작업을 의미하며, 조회는 데이터를 읽는 작업을 의미
- 구성요소
- Command Handlers : 데이터를 변경하는 작업을 처리, 이때 메시지큐를 사용해 명령이 큐에 저장되고, 비동기적으로 처리
- Query Handlers: 데이터를 조회하는 작업을 처리, 데이터 조회는 즉각적으로 처리될 수 있지만, 명령은 비동기적으로 처리되어 데이터 일관성을 유지
- Event Sourcing : 모든 상태 변경을 이벤트로 기록하고, 이벤트를 통해 시스템의 상태를 재구성하는 방식
c) 사가 패턴 (Saga Pattern)

- 분산 트랜잭션을 처리할 때 사용되는 아키텍쳐 패턴으로, 각 서비스에서 독립적으로 트랜잭션을 처리하지만, 전체 프로세스는 논리적으로 하나의 트랜잭션처럼 보이게 함
- 사가 패턴은 각 서비스에서 처리된 결과를 비동기적으로 전달받아 트랜잭션을 완성하거나 실패했을 경우 보상 작업을 수행
- 구성요소
- Saga Coordinator : 트랜잭션의 시작과 종료를 관리하며, 중간에 트랜잭션에 실패할 경우 보상 작업을 실행
- Local Transactions : 각 서비스에서 실행되는 독립적인 트랜잭션으로 각 서비스는 메시지 큐를 통해 비동기적으로 트랜잭션 결과를 전달
d) 백프레셔 패턴 (Backpressure Pattern)
- 시스템이 과부하 상태일 때 요청을 거부하거나 처리 속도를 늦추는 방식으로 트래픽을 조절하는 아키텍쳐 패턴
- 비동기 메시징 시스템과 함께 사용되며, 대규모 트래픽 상황에서 시스템의 안정성을 보장하는 데 도움
- 구성요소
- Producer : 메시지를 생성하여 큐에 넣는 역할을 하디만, 큐가 가득 차면 백프레셔를 통해 메시지 생산을 중단하거나 속도를 늦춤
- Consumer: 메시지를 처리하는 소비자로서, 큐에서 처리할 수 있는 메시지의 양을 제어하여 시스템과부하를 방지
e) Durable Messaging Pattern
- 메시지를 손실 없이 처리할 수 있도록 보장하는 패턴
- 메시지가 중간에 손실되거나 누락되지 않도록 메시지를 저장하고, 시스템 장애 시에도 복구가 가능한 상태로 유지
- 구성요소
- Persistent Queue : 메시지가 시스템에 도착하면 큐에 영구적으로 저장, 메시지는 실패 시 재시도될 수 있으며, 시스템이 복구된 후에도 메시지가 손실되지 않음
- Retry Mechanism : 실패한 메시지를 재처리할 수 있는 메커니즘을 포함하여, 메시지가 손실도지 않도록 보장
tmi 1
이벤트 버스랑 메시지 브로커랑 개념이 너무 비슷한데 왜 따로 나눠쓰는지 정확하게 이해가 안가서 예시를 짚고가고자 질문을 함
GPT: 와우… 이제 진짜 핵심 질문 나왔네요! 🔥
"이벤트 버스(Event Bus)와 메시지 브로커(Message Broker)는 같은 개념인가?"
→ 얼핏 보면 비슷해 보이지만, 완전히 같지는 않습니다!
둘은 비슷한 역할을 하지만, 의도와 사용 방식, 스코프가 다릅니다.
이벤트 버스 | 메세지 브로커 | |
개념 | 내부 시스템 간 이벤트 전달 | 독립 서비스 간 메시지 전달 |
역할 | 컴포넌트 간 느슨한 연결 | 시스템 간 안정적 메시지 교환 |
범위 | 애플리케이션 내부 또는 모놀리식 구조 | 마이크로서비스 간 or 시스템 간 |
전송 방식 | 대부분 메모리 기반, 경량 | 디스크 기반, 네트워크 기반 |
기술 예시 | Spring Event, Guava EventBus, NestJS EventEmitter | Kafka, RabbitMQ, ActiveMQ, Amazon SQS |
확장성 | 제한적 (단일 프로세스 중심) | 고성능, 대규모 확장 지원 |
전송 신뢰성 | 낮거나 없음 (기본적으로 fire-and-forget) | 매우 높음 (ack, retry, durable queue 등) |
🔹 이벤트 버스(Event Bus)
- 목적: 내부 객체나 컴포넌트들끼리 메시지(이벤트)를 주고받도록 하는 패턴
- 일반적으로 싱글 프로세스 환경에서 경량으로 동작
- 대표 사례:
- Spring ApplicationEventPublisher
- Google Guava EventBus
- NestJS의 EventEmitter
🧠 "한 애플리케이션 내부에서 A → B → C 흐름을 느슨하게 연결하고 싶을 때" 사용
🔹 메시지 브로커(Message Broker)
- 목적: 서로 다른 시스템 간에 메시지를 안정적으로 전달하는 인프라 컴포넌트
- 대부분 네트워크 기반, 디스크 저장 및 재시도, 장애 복구 기능 포함
- 대표 사례:
- Apache Kafka
- RabbitMQ
- Amazon SNS/SQS
- Google Pub/Sub
🧠 "마이크로서비스 간 통신"이나 "이벤트 중심의 확장성 있는 구조"에서 사용
그래서 결론은?
🔸 같은 개념은 아니고,
🔹 기능은 일부 겹치지만, 사용 목적과 범위가 다르다!
- 이벤트 버스는 애플리케이션 내부 이벤트 통신
- 메시지 브로커는 시스템 간/서비스 간 메시지 교환
🎯 용도에 따른 정리
앱 내부에서 컴포넌트 간 통신 | ✅ 이벤트 버스 |
마이크로서비스 간 이벤트 통신 | ✅ 메시지 브로커 |
네트워크 기반, 확장 가능한 구조 | ✅ 메시지 브로커 |
가볍고 빠른 로컬 이벤트 전달 | ✅ 이벤트 버스 |
tmi 2
위의 차이를 이해하게됨, 근데 왜 강의에서는 이벤트 버스 예를 주문 - 결제, 배송으로 들었는지 궁금함
GPT:
지금 말하신 부분은 실무에서도 많이들 혼동하는 포인트예요.
"이벤트 버스는 내부용이라면서, 왜 주문-결제-배송 간 이벤트 통신에 쓴다고 하지?"
→ 이건 정확히 어떤 ‘규모’와 ‘경계’를 말하느냐에 따라 완전히 달라져요.
✅ 핵심 정리 먼저!
이벤트 버스는 일반적으로 ‘하나의 애플리케이션 내부 컴포넌트 간 통신’에 사용하는 것이 맞습니다.
그런데, 서비스가 모두 한 애플리케이션 안에 있을 경우, 주문-결제-배송을 이벤트 버스로 연결할 수도 있어요.
하지만 마이크로서비스처럼 각각이 독립된 배포 단위일 경우는 메시지 브로커를 써야 합니다.
🔹 [예제 1] 작은 규모 / 단일 애플리케이션 기반
✨ Spring Boot 하나에 주문, 결제, 배송 모듈이 모두 존재
📦 구조 예시:
- OrderService
- PaymentService
- ShippingService
🧠 이 경우:
- 모든 서비스는 같은 JVM 내에서 실행
- 동기 호출보다 느슨한 연결이 필요함
- 따라서 Spring의 ApplicationEventPublisher 같은 이벤트 버스 패턴 사용 가능!
// 주문 완료 → 이벤트 발행
publisher.publishEvent(new OrderCreatedEvent(order));
// 결제 모듈이 이벤트 수신
@EventListener
public void handle(OrderCreatedEvent event) {
paymentService.pay(event.getOrder());
}
🔹 [예제 2] 대규모 마이크로서비스 아키텍처
✨ 주문, 결제, 배송이 각각 독립된 서비스로 운영되는 경우
📦 구조 예시:
- order-service (Spring Boot App)
- payment-service (Spring Boot App)
- shipping-service (Spring Boot App)
🧠 이 경우:
- 서로 다른 서비스는 네트워크를 통해 통신해야 함
- 한 서비스의 이벤트를 다른 서비스에 비동기 전파해야 함
- 이때는 Kafka / RabbitMQ 같은 메시지 브로커 사용이 필수
// order-service
kafkaTemplate.send("order.created", orderEvent);
// payment-service
@KafkaListener(topics = "order.created")
public void onOrderCreated(OrderCreatedEvent event) {
paymentService.pay(event);
}
📌 실무에서의 쓰임 요약
사용처 | 이벤트 버스 | 메시지 브로커 |
모놀리식(Spring 내부 모듈) | ✅ 적합 | ❌ 과함 |
마이크로서비스 (다른 서비스 간) | ❌ 불가 | ✅ 필수 |
빠르게 처리하고 싶을 때 | ✅ 메모리 기반이라 빠름 | ✅ 튼튼하지만 약간 느림 |
복구, 재시도 필요 | ❌ 기능 없음 | ✅ 기능 풍부 |
tmi 3
위 답변을 이해하고, 그럼 실제로 어떤 경우 이벤트버스를 사용하는지 궁금해졌음
그럼 이벤트 버스는 어떤 컴포넌트 간 느슨한 결합시에 쓰는거야? 주문시스템 그런거 말구 ?
gpt :
"이벤트 버스는 언제 쓰는 거야? 주문 시스템 같은 도메인 말고, 어떤 컴포넌트들 사이에서 느슨하게 결합시키는 데 쓰이는 거야?"
→ 이 질문 진짜 잘 하셨어요.
‘도메인 레벨 이벤트’가 아니라, 기술적/아키텍처적 컴포넌트 사이 연결용으로 이벤트 버스를 쓰는 경우가 많거든요.
✅ 이벤트 버스는 이런 상황에서 사용해요
🎯 비즈니스 흐름이 직접적이지 않지만, 어떤 작업이 끝났을 때 “누군가 반응해야 하는” 경우
🔹 1. 파일 업로드 후 후속 작업
- 파일 업로드 완료 → 썸네일 생성
- 파일 업로드 완료 → DB 기록 로그
- 파일 업로드 완료 → Slack 알림
🧠 업로더 컴포넌트는 "썸네일 생성자"가 있는지도 모르고 그냥 이벤트만 던짐
→ FileUploadedEvent 전파
🔹 2. 사용자 회원가입 이후 후속 처리
- 유저 가입 완료 → 이메일 발송
- 유저 가입 완료 → 추천인 포인트 적립
- 유저 가입 완료 → 마케팅 푸시 등록
🧠 UserService는 후속 동작을 신경 쓰지 않음
→ UserRegisteredEvent 발행 → 여러 리스너가 반응
🔹 3. 관리자 설정 변경 시 여러 모듈에 반영
- 관리자 UI에서 설정 변경 → 캐시 무효화
- 관리자 설정 변경 → 감사 로그 기록
- 관리자 설정 변경 → 시스템 전반에 브로드캐스트
🧠 AdminSettingService는 구체적인 반응을 몰라도 됨
→ ConfigChangedEvent 전파
🔹 4. 애플리케이션 부팅 이벤트 처리
- Spring Boot 실행 완료 후 초기화
- DB 초기 로딩
- 외부 API 호출 준비
🧠 ApplicationReadyEvent 사용
@EventListener(ApplicationReadyEvent.class)
public void onStart() {
System.out.println("앱 시작 시 초기화 수행!");
}
🔹 5. 도메인 외 관찰성, 모니터링, 감사 로그 처리
- 주문 생성 시 → AuditLogService가 로그 남김
- 결제 성공 시 → MonitoringService가 메트릭 기록
🧠 비즈니스 흐름에는 영향 없음
→ 하지만 리스너를 통해 부가 기능 연결
네.. 오늘도 챗과장님이 궁금증 해소 마무리 시켜주셨뜸 감사여!
참고, 강의 및 구글링
1티어 패션 커머스의 세일 도메인 프로젝트로 배우는 대규모 트래픽을 견디는 실전 백엔드의 모
실전 대용량 트래픽 처리의 모든 것! 대규모 시스템 설계부터 기능 구현, 테스트까지!
fastcampus.co.kr
'대용량 시스템 > 대규모 트래픽 이론' 카테고리의 다른 글
[대규모트래픽 이론] #3.1 대규모 트래픽 처리 개요 (0) | 2025.04.06 |
---|---|
[대규모트래픽 이론] #2.3 비동기 처리 시스템의 장단점 및 사례 (0) | 2025.04.06 |
[대규모트래픽 이론] #2.1 비동기 처리 아키텍처 이해와 확장 (0) | 2025.03.29 |
[대규모트래픽 이론] #1.2 동시성 처리와 비동기 처리의 기본 구조 (0) | 2025.03.29 |
[대규모트래픽 이론] #1.1 동시성 처리와 비동기 처리의 기본 개념 (0) | 2025.03.11 |