Kafka를 활용한 이벤트 기반 아키텍처 구축 #우아콘2023 #우아한형제들 (youtube.com)
위 동영상을 회고하는 글 입니다.
이벤트 기반 아키텍처를 왜?
배달 시스템의 복잡도 증가
배달 시스템이 커지면서 단순 배달 기능 외에 통계, 알림, 쿠폰 발급, 배달 시간 관리 등 다양한 기능이 요구되고 있습니다. 배달 시스템은 단순히 배달만 잘 수행하길 원했지만, 고객에게 실시간 알림을 제공하고 통계를 위한 데이터를 수집하며 쿠폰을 발급하는 등 복잡도가 크게 증가하고 있습니다.
이런 상황에서 이벤트 기반 아키텍처를 도입하면 시스템 복잡도를 낮추면서도 기능별로 유연하게 확장할 수 있습니다. 이벤트 기반 아키텍처는 핵심적인 배달 흐름과 부가 기능을 분리해 배달의 일관성에 영향을 주지 않고도 통계나 알림 같은 부가 기능을 비동기적으로 처리하게 합니다. 대부분 부가 기능은 배달과의 강한 일관성을 필요로 하지 않으며, 배달 데이터가 나중에 반영되는 최종 일관성만으로도 충분합니다.
이벤트는 어떤 정보를 가지고 있어야 하는가?
이벤트 구성 요소
마틴 파울러는 Domain Event를 "도메인에 영향을 미치는 관심 정보"라고 정의하며, 이는 대상, 행위, 정보, 시간을 포함합니다. 예를 들어, ‘배달이 A라이더에게 11시에 배차되었다’라는 이벤트는 다음과 같은 요소를 포함하여 정의될 수 있습니다.
- 대상 식별자: 이벤트가 발생한 대상의 식별자로, 어떤 대상(여기서는 배달)이 이벤트의 주체인지 명확히 나타냅니다.
- 행위: 이미 발생한 사건이므로 과거형으로 표현합니다. 예를 들어, 배차, 운행 시작 등으로 배달 시스템 내의 특정 상태 변화나 행동을 설명합니다.
- 정보: 이벤트와 관련된 구체적인 정보가 포함되며, 배달 수단(자전거, 오토바이 등), 현재 상태(운행 중, 도착 등) 등 주요 속성을 전달합니다.
- 시간: 이벤트가 발생한 정확한 시각을 명시해 시간 흐름을 추적할 수 있게 합니다.
이벤트 예시
‘배달이 A라이더에게 11시에 배차되었다’라는 이벤트는 다음과 같이 JSON 형식으로 표현될 수 있습니다.
{
"eventId": "A라이더",
"eventType": "운행시작",
"data": {
"state": "운행중",
"배달수단": "자전거",
},
"occurenceDateTime": "2023-11-15 11:00:00"
}
이벤트 기반 아키텍처 적용 후 장점
- 배달 시스템 복잡도 감소: 배달 시스템은 배달에만 집중하며, 각종 변경 사항은 이벤트로 전송됩니다. 이에 따라 새로운 요구 사항이 발생해도 배달 기능을 변경할 필요 없이 이벤트 처리 로직을 추가하여 확장할 수 있습니다.
- 소비처와의 결합도 감소: 소비처는 배달 이벤트만 수신하여 배달 상태를 파악할 수 있습니다. 배달 시스템의 상세 정보 조회가 불필요해져 API 요청이 줄어들고 시스템 간 결합도가 낮아집니다.
- 데이터 분석의 유리함: 이벤트 기반 아키텍처를 통해 도메인 히스토리가 축적되므로 시간에 따른 데이터를 수집하고 분석하기에 용이합니다. 이를 통해 고객 통계와 운영 효율성을 높일 수 있습니다.
이벤트 처리 시 주의사항
- 이벤트 데이터의 관리: 이벤트 데이터를 무분별하게 추가하지 않도록 주의해야 합니다. 소비처에서 특정 데이터 요구가 많아지면 이벤트의 크기가 커지고 관리가 어려워질 수 있기 때문에, 행위자 기반의 핵심 데이터만 포함하는 것이 중요합니다.
- 이벤트 순서 보장: 이벤트는 발생 순서대로 전달되어야 하는 경우가 많습니다. 배달 과정에서는 주문 생성 → 배달 시작 → 배달 완료와 같은 순서가 중요하며, 이를 준수하지 않으면 시스템에 오류가 발생할 수 있습니다. 예를 들어 주문 취소 후 주문 생성 이벤트가 들어오는 경우가 발생하지 않도록 해야 합니다.
이벤트 순서 보장 방법
이벤트의 순서를 보장하기 위해 이벤트 파이프라인 구성이 필요하며, 일반적으로 메시지 브로커를 통해 이를 구현할 수 있습니다. 대표적인 메시지 브로커로는 카프카(Kafka)가 있으며, 다음과 같은 특징이 있습니다.
- 순서 보장: 카프카는 특정 Key에 대해 파티션을 활용해 순서를 보장합니다. 예를 들어, 배달 시스템에서는 배달 번호를 기준으로 이벤트를 발행하여 특정 배달의 이벤트 순서를 보장할 수 있습니다.
- 고성능 및 고가용성: 카프카는 파티션을 통해 데이터를 분산하고, 클러스터링을 통해 고가용성을 제공합니다. 이를 통해 대규모 데이터와 트래픽에도 안정적이고 빠르게 이벤트를 처리할 수 있습니다.
- 확장된 생태계 지원: 카프카는 Kafka Streams와 Kafka Connect 같은 다양한 도구를 제공하여 데이터 파이프라인 구축, 데이터 스트리밍 처리, 데이터베이스 연결 등을 유연하게 관리할 수 있습니다.
- 운영 지원 도구: 카프카는 Kafka 클러스터를 관리하기 위한 전담팀 지원, 모니터링 및 관리 도구를 제공하여 안정적인 운영을 보장할 수 있습니다.
도메인 상태 != 이벤트 발행 결과
이벤트 기반 아키텍처에서 이벤트 발행 실패는 시스템의 도메인 상태와 실제 이벤트 발행 결과가 일치하지 않는 문제를 야기할 수 있습니다. 예를 들어, EBS 볼륨 이슈, 네트워크 이슈, 주키퍼(Zookeeper) 통신 문제 등으로 인해 이벤트 발행이 실패하거나 재시도될 때 이벤트의 순서가 꼬여버리면, 도메인의 상태가 일관성을 잃고 시스템 장애로 이어질 수 있습니다. 이를 방지하기 위해 Transactional Outbox 패턴과 Debezium을 활용한 메시지 릴레이가 효과적인 해결책이 됩니다.
Transactional Outbox 패턴
Transactional Outbox 패턴은 이벤트 기반 아키텍처에서 도메인의 상태와 이벤트 발행 결과 간의 일관성을 보장하기 위해 사용됩니다. 이 패턴은 도메인 처리 트랜잭션과 발행해야 할 이벤트를 하나의 트랜잭션으로 묶어 Outbox 테이블에 이벤트를 저장합니다. 이렇게 하면 도메인의 상태와 이벤트 발행이 동시에 커밋되어 일관성을 유지할 수 있습니다.
이후, 메시지 릴레이(Message Relay)가 Outbox 테이블의 이벤트를 순서대로 읽어 발행함으로써, 이벤트 발행의 순서와 정확성을 보장합니다. 이러한 방식은 이벤트 발행의 실패로 인한 문제를 최소화하고 시스템의 안정성을 높입니다.
Debezium 기반 메시지 릴레이
Debezium은 이벤트 발행을 위한 메시지 릴레이에서 사용하는 오픈소스 플랫폼으로, 데이터베이스에서 발생하는 변경 사항을 감지하고 타 시스템에 전송합니다. Debezium은 Outbox 테이블에서 발생한 변경 사항을 읽어 Kafka와 같은 메시지 브로커로 이벤트를 전송하며, 이 과정에서 이벤트 발행 순서와 일관성을 보장해줍니다.
Debezium을 선택한 이유:
- 저비용: Debezium은 설정을 통해 간단히 등록, 실행 및 모니터링이 가능해 비용 효율적입니다.
- 안정성: Debezium은 Binary Log를 통해 이벤트 순서를 보장하며, Kafka의 Offset을 활용하여 이벤트 발행을 확실히 보장합니다.
- 처리량: Outbox 테이블 파티셔닝을 통해 높은 처리량을 지원할 수 있습니다. 그러나 이벤트 발행 순서를 보장하기 위해 Debezium의 테스크 수는 하나로 고정하는 것이 필요합니다.
이벤트 활용 사례 및 아키텍처 확장
- 이벤트 스트림을 통한 CQRS 구현: 이벤트 스트림은 명령(Command)과 조회(Query) 작업을 분리하는 CQRS 패턴을 구현하는 데 활용될 수 있습니다. CQRS는 시스템의 확장성과 성능을 개선하며, 장애 발생 시 쿼리 쪽에만 영향을 미치도록 해 커맨드 작업이 계속 수행될 수 있도록 합니다.
- 데이터 분석 환경 구축: 이벤트 스트림을 데이터 분석에 활용해 시스템 성능과 운영을 최적화할 수 있습니다. 이를 위해 Kafka와 S3 Sink Connector를 통해 데이터를 Amazon S3에 저장하고, Glue, Athena, Apache Airflow, Data Lake 등을 활용해 데이터를 수집, 분석, 시각화하는 환경을 구성할 수 있습니다.
- 실시간 스트림즈 애플리케이션: 주기적 배치 집계에서 실시간 집계로 전환하기 위해, 이벤트 스트림을 기반으로 실시간 배달 라이더 수를 모니터링하는 스트림즈 애플리케이션을 구현할 수 있습니다. Kafka Streams를 활용하여 실시간 이벤트 데이터를 처리함으로써 즉각적인 모니터링이 가능해지며, 실시간 대응이 필요한 서비스에서 유용하게 사용할 수 있습니다.
이러한 방식으로 이벤트 기반 아키텍처는 이벤트 스트림을 통해 CQRS, 데이터 분석, 실시간 모니터링 등을 지원하여, 시스템의 복잡도를 줄이면서도 안정성과 확장성을 높이는 데 기여합니다.
'Development > Reflection' 카테고리의 다른 글
[Reflection] ㄷㄷㄷ: Domain Driven Design과 적용 사례공유 / if(kakao)2022 (1) | 2024.09.08 |
---|---|
[Reflection] [우아콘2020] 수십억건에서 QUERYDSL 사용하기 (0) | 2024.09.03 |
[Reflection] [우아콘2020] 수십억건에서 QUERYDSL 사용하기 - Select 컬럼에 Entity 자제 (0) | 2024.09.03 |