[5] EDA

2025. 10. 20. 19:32·MSA/MSA 아키텍처

이벤트 기반 아키텍처(EDA) 이해하기

현대적인 분산 시스템, 특히 마이크로서비스 아키텍처(MSA)를 구축할 때 서비스 간의 효과적인 통신 방식은 시스템 전체의 성능과 확장성, 유지보수성에 큰 영향을 미친다. 전통적인 요청/응답(Request/Response) 모델은 구현이 직관적이지만, 서비스 간의 강한 결합(Tight Coupling)과 동기적 차단(Blocking) 문제를 야기할 수 있다. 이러한 문제들을 해결하고 보다 유연하고 탄력적인 시스템을 구축하기 위한 아키텍처 스타일이 바로 **이벤트 기반 아키텍처(EDA, Event-Driven Architecture)**이다.


EDA란 무엇인가?

**이벤트 기반 아키텍처(EDA)**는 시스템 내에서 발생하는 의미 있는 **사건(Event)**을 중심으로 구성 요소(마이크로서비스 등)들이 상호작용하는 아키텍처 스타일이다. 요청을 보내고 응답을 기다리는 대신, 시스템의 상태 변화나 중요한 발생을 나타내는 이벤트를 **발행(Publish)**하고, 이 이벤트에 관심 있는 다른 구성 요소들이 이를 **구독(Subscribe)**하여 필요한 작업을 비동기적으로 수행하는 방식이다.

  • 이벤트(Event): 시스템 내에서 발생한 주목할 만한 사건이나 상태 변경을 나타내는 데이터이다. (예: OrderPlaced, PaymentProcessed, UserRegistered) 이벤트는 과거에 발생한 사실(Fact)을 나타내며 불변(Immutable)하다.
  • 이벤트 생산자(Event Producer): 이벤트를 발생시키고 이벤트 채널(브로커)로 발행하는 컴포넌트이다.
  • 이벤트 채널/브로커(Event Channel/Broker): 생산자가 발행한 이벤트를 수신하여 관심 있는 소비자에게 전달하는 중간 매개체이다. Kafka, RabbitMQ 등이 대표적이다.
  • 이벤트 소비자(Event Consumer): 특정 이벤트에 관심을 가지고 구독하며, 이벤트를 수신했을 때 특정 로직(반응)을 수행하는 컴포넌트이다.

EDA는 어떻게 동작하는가?

  1. 이벤트 발생: 시스템 내에서 의미 있는 사건이 발생한다. (예: 사용자가 주문을 완료함)
  2. 이벤트 발행: 해당 사건을 감지한 서비스(이벤트 생산자, 예: order-service)는 발생한 사실을 담은 이벤트(예: OrderPlaced 이벤트)를 생성하여 이벤트 브로커(예: Kafka)로 보낸다. 생산자는 이 이벤트를 누가 소비할지에 대해 알 필요가 없다.
  3. 이벤트 전달: 이벤트 브로커는 수신한 이벤트를 해당 이벤트를 구독하고 있는 모든 소비자(Consumer)에게 전달한다.
  4. 이벤트 소비 및 반응: 각 소비자(예: catalog-service, notification-service)는 이벤트를 수신하고, 이벤트 내용에 따라 자신의 책임에 맞는 작업을 독립적으로 수행한다 (예: catalog-service는 재고 감소, notification-service는 알림 발송). 이 과정은 비동기적으로 처리된다.

이러한 방식을 통해 서비스들은 서로를 직접 호출하지 않고 오직 이벤트 브로커와 이벤트 자체에만 의존하게 되어 **느슨한 결합(Loose Coupling)**을 달성한다.


EDA의 장점 ✨

  • 느슨한 결합 (Loose Coupling): 생산자와 소비자는 서로의 존재나 구현 세부 사항을 알 필요가 없다. 이벤트를 통해 간접적으로 상호작용하므로, 개별 서비스의 수정이나 교체가 다른 서비스에 미치는 영향을 최소화한다.
  • 확장성 (Scalability): 특정 이벤트에 대한 처리량이 증가하면 해당 이벤트를 소비하는 Consumer 서비스만 독립적으로 확장(Scale-out)할 수 있다. 생산자나 다른 소비자는 영향을 받지 않는다.
  • 탄력성 (Resilience): 특정 Consumer 서비스에 장애가 발생하더라도, 이벤트 브로커가 이벤트를 보관하고 있으므로 해당 서비스가 복구된 후 이벤트를 처리할 수 있다. 또한, 한 소비자의 장애가 다른 생산자나 소비자에게 직접 전파되지 않는다.
  • 반응성 (Responsiveness): 작업이 비동기적으로 처리되므로, 생산자는 이벤트를 발행한 후 즉시 다른 작업을 수행할 수 있어 시스템 전체의 응답성이 향상될 수 있다.
  • 유연성 (Flexibility): 새로운 요구사항이 발생했을 때, 기존 시스템을 변경하지 않고 새로운 Consumer를 추가하여 이벤트에 반응하도록 쉽게 확장할 수 있다.

EDA의 고려사항 🤔

  • 복잡성 증가: 비동기 흐름, 이벤트 순서 보장(부분적), 중복 처리, 실패 처리 등을 관리하는 것이 동기식 모델보다 복잡할 수 있다. 전체적인 이벤트 흐름을 추적하고 디버깅하는 것이 어려울 수 있다.
  • 최종적 일관성 (Eventual Consistency): 이벤트가 처리되어 시스템 전체의 데이터가 일관성을 가지기까지 약간의 시간 지연이 발생할 수 있다. 실시간으로 강력한 데이터 일관성이 요구되는 경우에는 적합하지 않을 수 있다.
  • 메시지 브로커 의존성: 이벤트 브로커 자체의 가용성과 성능이 전체 시스템에 큰 영향을 미치므로, 안정적인 브로커 운영이 중요하다.
  • 개발 및 테스트: 비동기적인 특성으로 인해 종단 간(End-to-end) 테스트나 통합 테스트를 설계하고 실행하는 것이 더 복잡할 수 있다.

스키마 정의와 유효성 검증 (Schema Definition & Validation) 📜

EDA 환경에서는 서비스 간에 주고받는 **이벤트의 구조(Payload)**가 매우 중요하다. 이 구조가 명확하게 정의되고 관리되지 않으면, 생산자가 이벤트 형식을 변경했을 때 소비자가 이를 제대로 처리하지 못하는 문제가 발생할 수 있다.

JSON Schema (또는 Avro Schema, Protobuf Schema 등)는 이러한 문제를 해결하기 위해 사용된다.

  • 데이터 계약(Data Contract): 이벤트 페이로드의 구조, 필드, 데이터 타입, 제약 조건 등을 명세 파일(예: .json 스키마 파일)로 명확하게 정의하여 생산자와 소비자 간의 데이터 계약 역할을 한다.
  • 유효성 검증(Validation): 생산자가 이벤트를 발행하기 전이나 소비자가 이벤트를 처리하기 전에, 메시지가 정의된 스키마에 맞는지 검증할 수 있다. 이를 통해 잘못된 형식의 데이터로 인한 런타임 오류를 방지하고 시스템의 안정성을 높인다.
  • 버전 관리 및 진화(Versioning & Evolution): 스키마 변경 이력을 관리하고 호환성 규칙을 적용하여, 시스템 중단 없이 안전하게 이벤트 스키마를 변경(예: 필드 추가)할 수 있도록 지원한다. Schema Registry와 같은 도구를 사용하면 이러한 스키마 관리와 검증을 더욱 체계적으로 수행할 수 있다. joneconsulting 레포지토리의 README에서도 EDA에서 JSON Schema를 이용한 버전 관리 및 검증 처리의 중요성을 언급하고 있다.

JSON Schema를 적용한다는 것은:

  1. 명시적 계약 정의: order-created-topic으로 보낼 메시지의 페이로드가 정확히 어떤 필드(예: productId, quantity, unitPrice)를 가져야 하고, 각 필드의 데이터 타입(예: integer, number)은 무엇이며, 제약 조건(예: quantity는 1 이상)은 무엇인지를 .json 스키마 파일로 명확하게 정의하는 것이다.
  2. JSON
     
    // 예시: order-created-payload-v1.schema.json
    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "OrderCreatedPayload",
      "type": "object",
      "properties": {
        "productId": { "type": "integer" },
        "quantity": { "type": "integer", "minimum": 1 },
        "unitPrice": { "type": "integer", "exclusiveMinimum": 0 }
        // userId 등 필요한 필드 추가 정의
      },
      "required": [ "productId", "quantity", "unitPrice" ]
    }
    
  3. Producer 측 검증 (선택적): OrderService가 Kafka 메시지를 보내기 전에, 생성한 페이로드 JSON 문자열이 위에서 정의한 JSON Schema 규칙에 맞는지 검증하는 로직을 추가할 수 있다. (Java 라이브러리 사용, 예: everit-org/json-schema) 이를 통해 잘못된 형식의 메시지가 발행되는 것을 사전에 방지한다.
  4. Consumer 측 검증 (권장): KafkaConsumer가 메시지를 받아 처리하기 전에, 수신한 JSON 문자열이 예상하는 JSON Schema 규칙에 맞는지 검증하는 로직을 추가한다. 만약 스키마 검증에 실패하면, 해당 메시지는 잘못된 형식으로 간주하고 오류 처리(예: 로그 남기기, DLQ(Dead Letter Queue)로 보내기)를 수행하여 Consumer 서비스가 비정상 종료되는 것을 방지한다. 👍
  5. Schema Registry 활용 (더 진화된 방식): Confluent Schema Registry나 Apicurio Registry 같은 스키마 레지스트리를 도입하면, JSON Schema(또는 Avro/Protobuf 스키마)를 중앙에서 관리하고 버전 관리를 수행하며, Producer/Consumer가 메시지 직렬화/역직렬화 시 자동으로 스키마를 참조하고 검증하도록 구성할 수 있다. 이는 스키마 관리를 더욱 체계화하고 안전한 스키마 변경(Evolution)을 가능하게 한다. ✨

결론

이벤트 기반 아키텍처(EDA)는 마이크로서비스 환경에서 서비스 간의 느슨한 결합, 확장성, 탄력성을 달성하기 위한 강력한 아키텍처 스타일이다. Kafka와 같은 메시지 브로커를 활용하여 비동기적으로 이벤트를 주고받음으로써 시스템 전체의 반응성을 높일 수 있다. 하지만 구현의 복잡성, 최종적 일관성, 디버깅의 어려움 등 고려해야 할 사항도 존재한다. 특히, 안정적인 이벤트 통신을 위해서는 JSON Schema 등을 이용한 명확한 데이터 계약 정의와 유효성 검증 체계를 갖추는 것이 중요하다.

'MSA > MSA 아키텍처' 카테고리의 다른 글

[BASIC #2] Microservice Architecture 개요와 서비스 분해 전략  (0) 2026.03.02
[BASIC #1] 마이크로서비스 아키텍처의 이해: Monolithic에서 MSA까지  (0) 2026.03.02
[4] SAGA 패턴  (0) 2025.10.20
[3] CQRS  (0) 2025.10.20
[2] gRPC  (0) 2025.10.20
'MSA/MSA 아키텍처' 카테고리의 다른 글
  • [BASIC #2] Microservice Architecture 개요와 서비스 분해 전략
  • [BASIC #1] 마이크로서비스 아키텍처의 이해: Monolithic에서 MSA까지
  • [4] SAGA 패턴
  • [3] CQRS
h6bro
h6bro
백엔드 개발자의 기술 블로그
  • h6bro
    Jun's Tech Blog
    h6bro
  • 전체
    오늘
    어제
    • 분류 전체보기 (250) N
      • Java (18)
        • Core (9)
        • Design Pattern (9)
      • Spring (80)
        • Core (24)
        • MVC (6)
        • DB (10)
        • JPA (26)
        • Monitoring (3)
        • Security (11)
        • WebSocket (0)
      • Database (33)
        • Redis (15)
        • MySQL (18)
      • MSA (25) N
        • MSA 기본 (11)
        • MSA 아키텍처 (14) N
      • Kafka (30)
        • Core (18)
        • Connect (12)
      • ElasticSearch (11)
        • Search (11)
        • Logging (0)
      • Test (4)
        • k6 (4)
      • Docker (9)
      • CI&CD (10)
        • GitHub Actions (6)
        • ArgoCD (4)
      • Kubernetes (18)
        • Core (12)
        • Ops (6)
      • Cloud Engineering (4)
        • AWS Infrastructure (3)
        • AWS EKS (1)
        • Terraform (0)
      • Project (8)
        • LinkFolio (1)
        • Secondhand Market (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Cloud Engineering 포스팅 정리
  • 인기 글

  • 태그

    ㅈ
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
h6bro
[5] EDA
상단으로

티스토리툴바