이벤트 브로커

공부용·2025년 10월 6일

1. 이벤트 브로커 스타일이란?

이벤트 기반 아키텍처(EDA)의 개념

  • 이벤트 기반 아키텍처(Event-Driven Architecture, EDA)는 시스템의 각 구성 요소가 이벤트(Event)를 중심으로 통신하고 반응하는 구조를 가진다.
  • 한 컴포넌트가 이벤트를 발생시키면, 다른 컴포넌트는 해당 이벤트를 수신하여 적절한 동작을 수행한다.
  • 컴포넌트 간에는 명시적 호출(Explicit Invocation)이 아닌, 묵시적 호출(Implicit Invocation)로 연결되어있다.
  • 느슨한 결합(Loose Coupling)으로 시스템은 서로의 존재를 알 필요 없이 동작한다.
  • 이벤트가 발생하면, 이를 필요로 하는 서비스가 알아서 반응하는 비동기적 통신(asynchronous communication)이 이루어진다.

묵시적 호출(Implicit Invocation) 스타일과의 관계

  • 프로시저를 직접 호출하는 대신, 이벤트 알림이 다른 모듈의 프로시저를 호출하는 방식이다.
  • 컴포넌트는 하나 이상의 이벤트를 브로드캐스트하고, 다른 컴포넌트들은 자신이 관심 있는 이벤트에 등록하여 자동으로 호출된다.
  • 컴포넌트 간의 결합도를 낮춰 확장성과 재사용성을 높인다.

이벤트 브로커 스타일의 등장 배경

  • 여러 서비스나 모듈 간의 통신을 비동기적으로 처리하면서도 확장성과 내고장성을 보장하기 위해 등장
  • 컴포넌트들이 브로커를 통해 간접적으로 통신함으로써 시스템의 복잡도를 줄이고, 장애 전파를 방지한다.
  • Apache Kafka, RabbitMQ, Amazon EventBridge, Google Pub/Sub이 대표적인 기술이다.

2. 아키텍처 개요

이벤트 중심 통신 구조의 특징

  • 이벤트 브로커 스타일은 시스템의 컴포넌트들이 이벤트를 중심으로 통신하고 반응하는 구조를 가진다.
  • 각 컴포넌트는 명시적인 호출 없이 독립적으로 동작하며, 오직 자신이 관심 있는 이벤트에만 반응한다.
  • 이벤트가 발생하면(예: 주문 생성, 결제 완료, 재고 변경 등) 브로커가 이를 감지하고 관련된 구독자들에게 전달한다.
  • 이벤트를 발행한 서비스는 누가, 언제, 어디서 그 이벤트를 소비하는지 알 필요가 없다.

브로커 스타일과 중재자 스타일의 차이

구분이벤트 브로커 스타일이벤트 중재자 스타일
이벤트 전달 방식브로커가 단순히 이벤트를 중계중재자가 이벤트의 흐름(워크플로우)을 제어
구성 요소 간 관계느슨한 결합 (Loose Coupling)중재자에 의존 (Tight Coupling)
특징비동기 메시징, 높은 확장성, 단순 구조복잡한 비즈니스 로직 제어 가능
장점확장성, 성능, 내고장성 우수데이터 일관성, 오류 복구 용이
단점워크플로우 제어 어려움중재자 의존성, 성능 저하 가능
대표 기술Kafka, RabbitMQ, EventBridgeApache Camel, Mule, Spring Integration
  • 이벤트 브로커는 이벤트 파이프라인 중심 구조로, 서비스 간 통신을 단순화하고 빠르게 만든다.
  • 이벤트 중재자는 중앙 워크플로우 제어자로 이벤트 간 순서를 관리하고 복잡한 비즈니스 로직을 조정한다.

3. 구성 요소

이벤트 브로커 스타일은 이벤트를 매개로 한 비동기 통신 구조로 핵심 구성 요소들이 명확하게 역할을 나누어 시스템의 확장성과 복원력을 높인다.

1) 이벤트 발행자 (Event Publisher)

  • 이벤트의 흐름을 시작하는 컴포넌트다.
  • 예를 들어 주문 서비스는 주문 생성 이벤트를 발행하고, 결제 서비스는 결제 완료 이벤트를 발행할 수 있다.
  • 이벤트는 이벤트 브로커의 채널(토픽)로 전달되어 시스템 전체에 브로드캐스트된다.
  • 이벤트 발행 후에는 응답을 기다리지 않고 즉시 반환(비동기 처리)한다.

2) 이벤트 브로커 (Event Broker)

  • 이벤트를 수집, 저장, 분배하는 중간 관리자이다.
  • 발행자의 이벤트를 수신하여 구독자에게 전달한다.
  • 다음과 같은 기능들을 제공한다.
    • 토픽/채널 관리
    • 메시지 큐 관리 (acknowledgement, retry 등)
    • 라우팅 및 필터링 (topic-based routing, fan-out 등)
    • 내고장성 및 데이터 영속성 보장

3) 이벤트 구독자 (Event Subscriber)

  • 특정 이벤트를 구독(subscribe)하여 이를 비동기적으로 수신하고 처리하는 컴포넌트다.
  • 이벤트를 수신하면 비즈니스 로직을 실행하고 필요하다면 새로운 이벤트를 다시 발행하여 체인 형태의 흐름(event chain)을 만든다.
on("OrderCreated", (event) => {
  processPayment(event.orderId)
  publish("PaymentCompleted", { orderId: event.orderId })
})

4) 이벤트 스트림 프로세서 (Event Stream Processor)

  • 실시간으로 발생하는 이벤트 스트림을 분석, 변환, 집계하는 특화된 컴포넌트이다.
  • 단순한 브로커 역할을 넘어서, 데이터 흐름 안에서 새로운 이벤트를 만들어내거나 패턴을 감지한다.
  • 예를 들어 30초 안에 3건 이상의 결제 실패가 발생하면 FraudAlert 이벤트를 발행과 같은 복합 이벤트 처리를 수행할 수 있다.

5) 커넥터 (Connector)

  • 컴포넌트 간 통신을 담당하는 기술적 연결 요소로 JSON, Avro, XML등 데이터 포맷 변환을 지원한다.
  • 예를 들어, 주문 서비스가 Kafka 토픽에 JSON 메시지를 발행하면 배송 서비스는 해당 토픽을 Avro 포맷으로 구독해도 브로커가 자동 변환해준다.

요약

구성요소역할예시 기술
Event Publisher이벤트 생성 및 발행API Gateway, Application Service
Event Broker이벤트 수집, 저장, 분배Kafka, RabbitMQ, EventBridge
Event Subscriber이벤트 수신 및 처리Microservice Consumers
Event Stream Processor실시간 데이터 처리Flink, Spark, Kafka Streams
Connector통신 및 데이터 포맷 변환MQTT, gRPC, AMQP

4.동작 원리 (Workflow)

이벤트 브로커 스타일은 이벤트를 중심으로 컴포넌트 간의 비동기 통신이 이루어지는 구조이다.

전체적인 흐름 개요

  • 이벤트 브로커 스타일은 발행 -> 브로커 -> 구독의 구조로 이루어진다.
  • 컴포넌트들은 서로 직접 통신하지 않고, 반드시 브로커를 통해 이벤트를 주고받는다.
  1. 이벤트 발생 (Event Generation)

    • 사용자의 액선, 외부 시스템의 입력, 센서 데이터 등에서 이벤트 발생
  2. 이벤트 발행 (Publish)

    • 이벤트 발행자가 브로커에게 이벤트를 전송
    • 이때 이벤트는 특정 토픽이나 채널에 게시
  3. 이벤트 저장 및 라우팅 (Brokering & Routing)

    • 브로커는 이벤트를 큐(queue)에 저장, 해당 이벤트를 구독 중인 모든 구독자에게 라우팅.
    • 메시지 포맷 변환, 필터링, 재시도(retry), ack 관리 등도 이 단계에서 수행
  4. 이벤트 소비 (Consume)

    • 구독자는 자신이 관심 있는 이벤트를 수신하고 비즈니스 로직을 실행한다.
    • 처리 후, 필요하다면 새로운 이벤트를 발행할 수 있다.

비동기 처리 구조의 특징 (장점)

  • 확장성 (Scalability): 구독자 수에 관계없이 시스템이 쉽게 확장됨
  • 높은 응답성 (Responsiveness): 발행자는 즉시 반환되어 대기 시간이 없음
  • 내고장성 (Resilience): 한 구독자가 다운되더라도 큐에 남은 이벤트로 복구 가능
  • 비동기 워크플로우: 여러 이벤트가 병렬로 흐르며 자연스럽게 분산 처리됨

토폴로지

        ┌──────────────┐
        │ Event Broker │
        └──────┬───────┘
               │
   ┌───────────┼───────────┐
   │           │           │
Publisher A  Publisher B  Publisher C
   │           │           │
   ▼           ▼           ▼
 ┌───────────────────────────┐
 │         Event Topics       │
 └───────────────────────────┘
   │           │           │
   ▼           ▼           ▼
Subscriber 1  Subscriber 2  Subscriber 3
  • 모든 이벤트는 중앙의 브로커를 통해 분배되며, 서비스 간의 직접 호출이 존재하지 않는다.
  • 각 서비스는 독립적 배포(Independent Deployment)와 유연한 확장(Flexible Scaling)이 가능하다.

5. 단점

  1. 워크플로우 제어의 어려움

    • 비동기 이벤트 플로우는 명시적인 순서 제어나 트랜잭션 관리가 어렵다.
    • 이벤트가 언제, 어떤 순서로 처리될지 명확하지 않다.
    • 전체 흐름의 끝을 추적하기 어렵다.
    • 이벤트 간 종속성이 많은 경우 오케스트레이션(orchestration)이 필요.
    • 이때 이벤트 브로커 대신 이벤트 중재자 스타일이 더 적합할 수 있다.
  2. 에러 처리와 복구의 복잡성

    • 비동기 처리 특성상 이벤트가 실패했을 때 즉시 롤백하기 어렵다.
    • 재시도 로직, DLQ(Dead Letter Queue) 관리 필요
    • 메시지 중복 처리나 순서 보장(Ordering)이 어려움
  3. 데이터 일관성(Consistency) 문제

    • 분산된 이벤트 구조에서는 강한 일관성(Strong consistency)대신 최종적 일관성(eventual consistency)을 선택해야 하는 경우가 많다.
    • 동일한 이벤트가 여러 서비스에 전달될 때 시점 차이 발생
    • 예: 결제가 완료되기 전 배송이 시작되는 상황 방지 필요
    • SAGA 패턴, Outbox 패턴 같은 아키텍처적 보완 필요

6. 다른 아키텍처와비교

이벤트 브로커 vs 이벤트 중재자

  • 두 스타일 모두 이벤트 기반 구조이지만, 이벤트 브로커는 분산 처리 중심, 이벤트 중재자는 중앙 제어 중심이다.
구분이벤트 브로커 스타일이벤트 중재자 스타일
구조이벤트 브로커가 중간에서 단순 전달중앙 중재자가 워크플로우 제어
결합도느슨한 결합 (Loose Coupling)상대적으로 높은 결합 (Tight Coupling)
처리 방식비동기적, 병렬 처리순차적, 제어 흐름 기반
장점확장성, 복원력, 독립 배포 용이흐름 제어 용이, 일관성 유지
단점전체 프로세스 가시성 낮음단일 실패 지점(Single Point of Failure) 가능
주요 기술Kafka, RabbitMQ, EventBridgeApache Camel, Mule ESB, Spring Integration

이벤트 브로커 vs 발행-구독(Pub/Sub) 패턴

  • 이벤트 브로커 스타일은 기본적으로 Pub/Sub 패턴을 확장한 형태이다.
  • 하지만 단순 Pub/Sub은 중앙 브로커가 없거나, 메시지 전달 보장이 약하다.
구분Pub/Sub 패턴이벤트 브로커 스타일
중개자없음 (직접 통신)브로커가 존재
전달 보장약함 (Best Effort)강력함 (At-least-once, Exactly-once)
메시지 관리단순 알림 수준큐잉, 저장, 재시도 등 지원
확장성소규모 시스템 적합대규모 분산 환경 적합
예시Frontend EventBus, RxJSKafka, RabbitMQ, Pub/Sub

7. 설계 시 고려사항 (Design Consideration)

이벤트 브로커 스타일을 실제 시스템에 적용할 때는 단순한 메시지 전달 구조를 넘어서, 신뢰성과 유지보수성을 고려한 설계가 필요하다.

1) 이벤트 설계 원칙 (Event Design Principles)

  • 이벤트는 시스템 간의 계약(Contract) 역할을 하기 떄문에, 명확한 이벤트 이름, 데이터 스키마, 버전 관리가 중요하다.

2) 이벤트 중복 처리 (Idempotency)

  • 이벤트는 네트워크나 브로커 장애로 인해 중복 전송될 수 있다.
  • 구독자는 동일 이벤트를 여러 번 받아도 결과가 변하지 않도록(idempotent) 설계해야 한다.
  • 이벤트 ID를 부여하고, 처리 기록을 저장하여 중복 실행 방지
  • 처리된 이벤트 목록 캐시나 DB 테이블 관리

3) 순서 보장 (Ordering)

  • 이벤트는 분산 환경에서 병렬로 처리되기 떄문에, 처리 순서가 보장되지 않을 수 있다.
  • 동일한 엔티티에 대한 이벤트는 동일한 파티션(Partition Key)으로 보내기
  • 순서 의존성이 높을 경우 중재자 (Mediator) 또는 트랜잭션 관리 도입

4) 재시도 및 장애 복구 (Retry & Fault Recovery)

  • 비동기 구조에서는 일시적 장애가 발생할 수 있으므로, 재시도 로직(retry) 과 DLQ(Dead Letter Queue) 설계가 필수이다.
  • 이벤트 처리 실패 시 -> DLQ로 이동
  • 일정 시간 후 자동 재시도 or 수동 복구 *(관련 프로젝트 진행 시 QnA에서 가장 많이 물어보던 질문)
  • 장애 원인에 따라 처리 정책 구분

5) 모니터링 및 트레이싱 (Monitoring & Tracing)

  • 이벤트 기반 구조는 흐름이 분산되어 있어 디버깅과 장애 추적이 어렵다
  • 이벤트 단위로 추적 가능한 모니터링 체계가 필요하다.
profile
공부 내용을 가볍게 적어놓는 블로그.

0개의 댓글