메시징 및 이벤트 기반 아키텍처 (Event-Driven Architecture)
목차
- 이벤트 기반 아키텍처란
- 왜 이벤트 기반 설계를 도입하는가
- 메시지 큐와 이벤트 스트림
- 이벤트 소싱과 CQRS 개요
- 비동기 처리, 재시도, 중복 처리
- 언제 도입할까
- 이벤트 기반 아키텍처의 트레이드오프
- 면접 포인트
- 참고 자료
이벤트 기반 아키텍처란
이벤트 기반 아키텍처(Event-Driven Architecture) 는 서비스가 직접 서로를 동기 호출하기보다, 이벤트를 발행하고 다른 서비스가 이를 구독해 반응하도록 설계하는 방식입니다.1
이 문서는 시스템 설계 관점에서 왜 동기 호출 대신 이벤트를 선택하는지, 언제 메시징이 필요한지, 그 대가가 무엇인지를 설명합니다.
Kafka, RabbitMQ, ack, consumer group 같은 구현 상세는 메시징 시스템 문서가 더 직접적인 심화 자료입니다.
핵심은 “큐를 도입한다”가 아니라, 서비스 간 결합도와 처리 타이밍을 어떻게 느슨하게 만들 것인가를 설계하는 데 있습니다.
왜 이벤트 기반 설계를 도입하는가
이벤트 기반 설계는 보통 다음 문제를 풀기 위해 등장합니다.
- 동기 호출 체인이 길어짐
- 하나의 요청에 후속 작업이 많음
- 트래픽 spike를 바로 처리하기 어려움
- 서비스 간 결합도가 높아져 변경이 어려움
예를 들어 주문 생성 후 다음 작업이 이어질 수 있습니다.
- 결제 승인
- 재고 차감
- 알림 발송
- 분석 적재
이 모든 단계를 동기 호출로 묶으면 다음 문제가 생깁니다.
- 한 서비스 지연이 전체 응답 시간을 늘림
- 일부 실패가 전체 실패로 번짐
- 후속 작업을 추가할수록 결합도가 커짐
그래서 이벤트 기반 설계는 즉시 처리해야 하는 핵심 경로와 나중에 처리해도 되는 후속 흐름을 분리하는 방식으로 이해하면 좋습니다.
메시지 큐와 이벤트 스트림
이벤트 기반 설계에서는 보통 큐 기반 메시징과 스트림 기반 메시징을 구분해서 설명합니다.
| 항목 | 메시지 큐 중심 | 이벤트 스트림 중심 |
|---|---|---|
| 주 목적 | 작업 분산과 비동기 처리 | 이벤트 보존과 재처리 |
| 대표 도구 | RabbitMQ, SQS | Kafka, Pulsar |
| 강점 | 작업 큐, 라우팅, 백그라운드 잡 | 이벤트 버스, 로그, 분석, 재소비 |
| 주의점 | 재처리와 장기 보존에는 한계가 있을 수 있음 | 운영 복잡도와 데이터 모델링 부담이 커질 수 있음 |
설계 관점에서 중요한 질문은 다음입니다.
- 지금 필요한 것이 작업 큐 인가
- 아니면 이벤트 로그와 재처리 기반 구조 인가
즉, “Kafka가 더 좋다”가 아니라 무엇을 전달하고, 얼마나 오래 보존하고, 재처리가 필요한가가 선택 기준입니다.
관련 구현 상세는 메시징 시스템 문서에서 더 구체적으로 다룹니다.
이벤트 소싱과 CQRS 개요
이벤트 기반 설계를 이야기하다 보면 이벤트 소싱(Event Sourcing) 과 CQRS(Command Query Responsibility Segregation) 가 자주 함께 나옵니다.
이벤트 소싱
현재 상태만 저장하는 대신, 상태를 만든 이벤트의 흐름 자체를 저장하는 방식입니다.2
- 장점: 변경 이력을 자연스럽게 남길 수 있음
- 장점: 재생(replay)과 감사 추적에 유리함
- 주의점: 이벤트 스키마 진화와 재생 비용이 커질 수 있음
CQRS
쓰기 모델과 읽기 모델을 분리하는 방식입니다.3
- 장점: 읽기 패턴에 맞춘 조회 모델을 따로 최적화 가능
- 장점: 이벤트 기반 업데이트와 잘 맞음
- 주의점: 읽기/쓰기 모델 간 일시적 불일치를 감수해야 함
| 패턴 | 언제 유리한가 | 대가 |
|---|---|---|
| 이벤트 소싱 | 변경 이력, 감사 추적, 재생이 중요한 경우 | 모델과 운영 복잡도 증가 |
| CQRS | 읽기 패턴이 다양하고 쓰기 모델과 충돌하는 경우 | 최종적 일관성과 동기화 설계 필요 |
면접에서는 이 패턴들을 “최신 아키텍처”처럼 말하기보다, 특정 요구가 있을 때만 도입하는 고비용 구조로 설명하는 편이 더 안전합니다.
비동기 처리, 재시도, 중복 처리
이벤트 기반 설계는 결합도를 낮추는 대신, 실패 처리를 더 신중하게 설계해야 합니다.
대표 포인트는 다음과 같습니다.
- 재시도: 일시 장애를 흡수하되 무한 재시도 폭주를 막아야 함
- 중복 처리: at-least-once 전달을 감안해 idempotency가 필요함
- DLQ: 반복 실패 이벤트를 어디로 격리할지 정해야 함
- 순서 보장 범위: 전역 순서가 아니라 보통 파티션/키 단위 순서를 다룸
- 관측성: lag, retry count, 처리 실패율을 봐야 함
예를 들어 주문 이벤트를 처리할 때는 다음과 같은 질문이 붙습니다.
- 결제 이벤트가 두 번 오면 어떻게 막을 것인가
- 재고 차감 실패 시 재시도와 보상은 어떻게 할 것인가
- 알림 발송 실패가 주문 생성까지 되돌려야 하는 문제인가
관련 일관성 논의는 데이터베이스 트랜잭션과 일관성, 분산 시스템 문서와 연결됩니다.
언제 도입할까
이벤트 기반 아키텍처는 보통 다음 조건이 명확할 때 도입 가치가 큽니다.
- 후속 작업이 많아 동기 호출 체인이 길어질 때
- 일부 작업은 지연 허용이 가능할 때
- 생산자와 소비자의 배포 주기를 분리하고 싶을 때
- spike를 버퍼링하고 재처리할 필요가 있을 때
반대로 아직 늦추는 편이 나은 경우도 있습니다.
- 서비스 수가 적고 동기 흐름만으로 충분할 때
- 일관성과 디버깅 단순성이 더 중요할 때
- 운영 인력이 메시징 계층 복잡도를 감당하기 어려울 때
즉, 이벤트 기반 설계는 “비동기면 더 좋다”가 아니라, 응답 경로와 후속 처리 경로를 분리할 가치가 분명할 때 선택하는 구조입니다.
이벤트 기반 아키텍처의 트레이드오프
- 장점: 서비스 간 결합도를 낮추고, 비동기 처리와 재처리를 쉽게 만들 수 있습니다.
- 단점: 최종적 일관성, 디버깅 난이도, 메시지 스키마 관리 부담이 커집니다.
- 주의점: 이벤트를 도입하면 시스템이 더 빨라진다기보다, 실패와 데이터 흐름을 더 복잡하게 다뤄야 합니다.
특히 다음 오해를 피해야 합니다.
- 큐를 넣으면 자동으로 확장성이 해결되는 것은 아님
- 이벤트 기반이라고 해서 무조건 마이크로서비스에 유리한 것은 아님
- exactly-once를 시스템 전체에서 쉽게 얻을 수 있다고 말하면 위험함
좋은 답변은 어떤 후속 작업을 비동기로 빼는지, 어떤 데이터 불일치를 허용하는지, 재시도와 중복 처리를 어떻게 감당할지를 함께 설명하는 답변입니다.
면접 포인트
- 이벤트 기반 아키텍처의 핵심은 큐 도입이 아니라 동기 흐름과 후속 처리를 분리하는 설계입니다.
- 메시지 큐와 이벤트 스트림은 저장 모델과 재처리 목적이 다르므로 구분해서 설명해야 합니다.
- 이벤트 소싱과 CQRS는 필요가 분명할 때만 도입하는 고비용 구조로 설명하는 편이 좋습니다.
- 비동기 처리에서는 retry, idempotency, DLQ, 순서 보장 범위를 같이 말해야 답변이 강합니다.
- 좋은 답변은 왜 동기 호출 대신 이벤트를 선택하는지와 그 대가를 함께 설명합니다.