9/22

졸용·2025년 9월 22일

TIL

목록 보기
80/144

🔹 분산추적이란?

MSA와 같은 분산 시스템에서 서비스 간의 요청 흐름을 추적하고 모니터링하는 방법을 말한다

예)
MSA 환경에서는 하나의 클라이언트 요청이 여러 서비스를 거쳐야 한다.
API Gateway → 인증 서비스 → 주문 서비스 → 결제 서비스 등

문제 발생 시 어느 서비스에서 지연이 발생했는지, 어디서 에러가 발생했는지 추적하기 어렵기 때문에 분산추적을 사용하여 전체 요청의 흐름을 시각화할 수 있다.



🔹 이벤트 드리븐 아키텍처란(EDA)?

시스템에서 발생하는 이벤트(상태 변화나 행동)를 기반으로 동작하는 소프트웨어 설계 스타일을 말한다

이벤트는 비동기적으로 처리되며, 서비스 간의 느슨한 결합을 통해 독립적으로 동작할 수 있게 한다.

3요소로 이벤트 드리븐 아키텍처라는 개념의 큰 그림을 잡을 수 있다.

  1. 이벤트 소스 (또는 publisher):
  • 의미: "무슨 일이 일어났는가"의 기원 (도메인 객체, 서비스, DB의 변경)
  • 역할: 상태가 변경된 후 이벤트를 생성하는 역할
  • 핵심 포인트: 중복 방지용 enentId 생성, 트랜잭션과 발행의 원자성(Outbox)
  1. 이벤트 버스 (또는 queue):
  • 의미: 이벤트의 전달/라우팅/내구성을 담당하는 중개자 역할 (메시지 브로커, 스트림 로그)
  • 역할: 토킥/큐로 라우팅, 파티션 단위 순서 보장, 보관/리플레이(스트림 계열), 역압/버퍼링
  • 핵심 포인트: 키 설계, 보존기간, 소비 지연 모니터링
  1. 이벤트 핸들러:
  • 의미: 이벤트를 구독해 후속 동작을 수행하는 소비자 (쓰기/조회 갱신/ 알림/ 사가 보상 등)
  • 역할: 멱등성(중복 처리), 리트라이/백오프, DLQ 분리, 최종 일관성 수용
  • 핵심 포인트: 사가, CQRS 읽기 모델 갱신

🔸 맵핑 (용어 대응)

EDA 요소Kafka 계열RabbitMQ 계열
이벤트 소스Producer / Outbox Publisher / CDC(Source Connector)Publisher / Outbox Publisher / CDC
이벤트 버스Topic + Partition + Log(브로커)Exchange + Queue(브로커)
이벤트 핸들러Consumer(Consumer Group)Consumer(Queue Consumer)

🔸 이벤트 드리븐 아키텍처의 장점

  • 느슨한 결합:

    • 서비스 간의 강한 종속성을 제거하여 독립적인 개발과 배포가 가능하도록 한다
    • 이벤트 기반 통신을 통해 서비스 간의 결합도를 낮춘다
    • 특정 이벤트를 여러 소비자가 동시에 활욜할 수 있다
  • 확장성:

    • 수평 확장에 용이해 대규모 시스템에서 유용하다
    • 이벤트 프로듀서와 컨슈머를 독립적으로 확장 가능하다
    • 장애 격리가 가능하다 (한 이벤트 핸들러만 죽어도 전체는 영향 없다)
    • 비즈니스 로직이 "이벤트 발생 → 반응" 형태로 자연스럽게 연결 가능하다
  • 비동기 처리:

    • 이벤트를 비동기적으로 처리해 시스템의 응답성을 향상시킬 수 있다
    • 요청과 응답을 비동기적으로 처리해 성능을 최적화시킬 수 있다

🔸 이벤트 드리븐 아키텍처의 단점

  • 복잡성 증가:

    • 이벤트 기반 통신으로 인해 시스템의 설계가 복잡하다
    • 운영 난이도가 높다 (메시지 브로커 운영 필요)
    • 디버깅/트랜잭션 관리가 까다롭다 (비동기 흐름)
    • 데이터 일관성 보장이 어렵다
  • 장애 전파:

    • 이벤트 실패 시 다른 서비스로 장애가 전파될 수 있다
    • 이벤트 재처리 및 장애 복구 매커니즘을 구현할 필요가 있다


🔹 Spring Cloud Stream이란?

Spring Boot 애플리케이션에서 메시지 브로커 (Kafka, RabbitMQ 등)와 쉽게 연결하여 이벤트 드리븐 아키텍처를 구현할 수 있도록 해주는 프레임워크를 말한다

개발자가 @Bean 함수 단위로 메시지 생상/소비 로직만 작성하면, Spring Cloud Stream이 나머지 바인딩, 직렬화, 에러처리, 재시도 로직을 대신 처리한다.


🔸 주요 개념

  • Binder:
    브로커별 어댑터 역할을 한다. (Kafka Binder, RabbitMQ Binder)
    "내 코드"와 "실제 브로커" 사이 연결을 담당한다.

  • Destination:
    메시지가 오고 가는 논리적 목적지 (토픽/큐 등)

  • Binding:
    애플리케이션 코드(Supplier/Consumer)와 Destination을 연결하는 설정

  • Message:
    payload + headers 구조의 데이터.
    Spring Messaging 표준 인터페이스 사용.


🔸 Spring Cloud Stream 쓰는 이유

  • 추상화:
    Kafka, RabbitMQ 등의 구체 브로커에 의존하지 않고 공통 API로 코딩이 가능하다.

  • 생산자/소비자 단순화:
    MessageChannel 이나 함수형 프로그래밍 모델(Supplier, Function, Consumer)로 쉽게 정의할 수 있다.

  • 운영 편의성:
    바인더 개념을 통해 브로커 종류를 교체할 때 애플리케이션 로직을 거의 수정할 필요 없다.

  • EDA 구축 용이:
    이벤트 기반 서비스 간 통신, CQRS 읽기 모델 갱신, 사가 패턴 등에 바로 활용이 가능하다.

profile
꾸준한 공부만이 답이다

0개의 댓글