[EDA] 이벤트 발행하기
애플리케이션에서 이벤트를 발행하는 방법은 크게 Application layer event와 Persistence layer event으로 나뉜다.
Application layer event
애플리케이션 안에서 명시적으로 이벤트를 발행하는 방법이다.
장점은 원하는 시점에 이벤트를 발행할 수 있다는 것이다. DB에 데이터가 적재되지 않는 상황에서도 이벤트를 발행할 수 있다.
단, 도메인과 DB가 명시적으로 분리되어있는 경우에만 사용가능하다. 만약 도메인과 DB를 다른 애플리케이션에서 사용하고 있는 경우, 이벤트를 감지하지 못하는 상황이 발생할 수 있다.
Persistence layer event
데이터 저장소를 활용하여 이벤트를 발행하는 방법이다. CDC가 대표적인 예이다.
이 방법은 도메인/DB가 분리되어있지 않거나, 애플리케이션에서 데이터를 변경하는 시점을 모두 파악하기 어려운 경우에 유용하다. DB에 저장된 데이터를 보고 이벤트를 발행하기 때문에 레거시 모놀리틱 애플리케이션에서도 손쉽게 이벤트를 발행할 수 있다.
이벤트 없이 MSA 환경에서 레거시 모놀리틱 애플리케이션과 연동하는 대안으로 다음과 같은 방법이 있다.
- 점대점으로 API를 호출하기
- 중간에 데이터 저장소를 두고 DB 덤프를 일정 주기마다 동기화하는 식으로 시스템 간에 벌크 데이터를 퍼나르는 이벤트와 비슷한 장치 만들기
그러나 위의 방법은 몇가지 단점이 있다.
전자는 하부 서비스에 있는 데이터를 직접 질의하는 경우 점대점 의존성이 높아진다.
후자는 데이터를 실시간으로 연동하지 못하고, 시스템을 확장할 때마다 신규 데이터 저장소 연동 워크 플로우를 구축해야한다는 단점이 있다.
기존 데이터 저장소를 활용하여 중앙화된 이벤트를 발행하는 방법을 data liberation (데이터 해방)이라고 부른다. 이 방식은 새로운 SSOT (single source of truth)으로 이벤트 데이터를 사용한다. 그리고 해당 이벤트를 필요로하는 각 시스템은 필요할 때마다 자유롭게 해당 이벤트를 가져갈 수 있다.
이 방법을 사용하면 적은 공수로 레거시 모놀리틱 애플리케이션을 이벤트 기반 아키텍처로 전환할 수 있다. 리팩토링 비용, 레거시 변경 리스크, 레거시 시스템 개발자 리소스 등을 줄일 수 있다.
Persistence layer에서 이벤트를 발행하는 방법은 크게 두가지로 나뉜다. 하부 데이터 저장소에서 데이터 추출하는 방법과 kafka connect 같은 CDC 도구를 사용한 중앙화된 데이터 해방 프레임워크를 사용하는 방법이다.
1. 데이터 해방 패턴
이 방법은 크게 쿼리 기반 (query-base), 로그 기반 (log-based), 아웃박스 테이블 기반 (table-based)으로 나뉜다.
(a) 쿼리 기반
이는 DB에서 쿼리한 결과를 이벤트로 발행하는 방법을 말한다.
쿼리 기반을 활용하여 데이터를 이벤트로 변환하는 작업 절차는 다음과 같다. 쿼리 기반으로 이벤트를 발행하려면 최초 1회에는 전체 데이터를 조회하여 이벤트를 발행하는 작업을 해야한다. 그리고 이후에는 변경분에 해당하는 데이터만 이벤트를 발행한다.
쿼리로 이벤트 발행 대상 선정
쿼리로 이벤트를 발행할 대상을 선택하는 방법은 크게 세가지이다.
- 최종 수정 시각 (updatedAt)을 기준으로 데이터 폴링하기
- 이 방법을 사용하려면 데이터 변경 시 항상 레코드 최종 수정 시각이 갱신되어야한다. 만약 최종 수정 시각이 갱신되지 않으면 이벤트가 유실된다.
- increment pk (자동증분 id)를 기준으로 데이터 폴링하기
- 커스텀 쿼리를 만들어서 데이터 폴링하기
- 반정규화된 커스텀 쿼리 혹은 뷰를 사용하면 불필요한 정보가 외부에 노출되는 것을 방지할 수 있다.
이 방식을 사용하려면 폴링 빈도와 업데이트 지연 시간을 결정해야한다.
단점
- 하드 딜리트가 불가능하다.
- DB 스키마와 이벤트 스키마 포맷 간에 의존성이 있다.
- DB 스키마가 변경되는 경우, 이벤트 스키마와 호환되지 않는 문제가 발생할 수도 있다.
- 데이터가 일정한 폴링 주기마다 동기화되기 때문에 동일한 레코드에 대한 여러 건의 변경이 하나의 이벤트로 보이게 된다. (간헐적 캡쳐/intermittent capture)
- 이벤트 발행 대상을 선정하는 쿼리가 데이터 저장소 성능에 영향을 미칠 수 있다.
(b) 로그 기반
하부 데이터 구조의 변경 내역을 기록한 붙임 전용 로그(change log)를 기준으로 추출한다. 데이터 변경 로그를 기록하는 저장소에서만 사용 가능하다.
장점
- 하드 딜리트가 가능하다.
- DB 성능에 미치는 영향을 최소화할 수 있다.
- 이벤트 발행 지연 시간이 짧다.
- 데이터 변경 사항이 로그에 기록되면 바로 이벤트를 전파할 수 있다.
단점
- 내부 데이터 모델이 노출될 수 있다.
- 체인지로그에 데이터가 원본 그대로 남는다.
- 체인지로그에는 데이터 변경 데이터만 들어있다.
- 정규화된 이벤트를 발행해야하는 경우, 다운스트림 마이크로 서비스가 외래 키를 조인하고 반정규화를 처리해야한다.
- DB 스키마와 이벤트 스키마 포맷 간에 의존성이 있다.
(c) outbox table 기반
출력 큐로 사용할 테이블에 데이터를 저장한다. 그리고 다른 스레드나 별도의 프로세스가 테이블을 쿼리해 데이터를 정해진 이벤트 스트림으로 내보낸 뒤, 관련 로우를 삭제한다.
장점
- 이벤트를 발행하기 전에 이벤트 스키마를 검증할 수 있다.
- 아웃박스 테이블에 값을 쓰기 전에 필요한 만큼 데이터를 반정규화할 수 있다.
- 아웃박스 테이블에 값을 쓰기 전에 직렬화하여 스키마의 유효성을 검증할 수 있다.
- 내부 데이터 모델이 불필요하게 노출되는 것을 방지할 수 있다.
단점
- 비즈니스 프로세스 성능에 영향을 미친다.
- 트랜잭션 안에 이벤트 스키마 유효성 검증 로직이 추가되는 경우, 성능에 영향을 미치게 된다. 그리고 오류가 발생하는 경우, 비즈니스 작업도 롤백된다.
- 이벤트를 발행하려면 애플리케이션 코드를 필수로 변경해야한다.
2. 데이터 해방 프레임워크
이는 카프카 커넥트, 아파치 고블린, 아파치 나이파이 같은 중앙화 프레임워크를 사용하여, 데이터를 이벤트로 발행하는 방법을 말한다. 이 2프레임워크를 사용하면 DB를 통해 얻은 결과를 이벤트로 발행할 수 있다. 그리고 필요시 인스턴스를 더 추가해서 CDC 작업 용량을 늘릴 수도 있다.
참고
https://hyperconnect.github.io/2021/01/11/cdc-platform.html
이벤트 기반 마이크로 서비스 구축 4장. 기존 시스템에 이벤트 기반 아키텍처 통합