메시징 및 이벤트 기반 아키텍처 (Event-Driven Architecture)

목차


이벤트 기반 아키텍처란

이벤트 기반 아키텍처(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, 순서 보장 범위를 같이 말해야 답변이 강합니다.
  • 좋은 답변은 왜 동기 호출 대신 이벤트를 선택하는지와 그 대가를 함께 설명합니다.

참고 자료