Engineering Story
Trigger 기반 동기화의 CDC 이벤트 파이프라인 전환
실시간 변경과 대량 backfill을 분리하고 재시도·알림·검증 경로를 갖춘 데이터 동기화 사례
- AWS DMS
- Kinesis
- Lambda
- PostgreSQL
왜 바꿔야 했는가
상품과 검색용 데이터를 맞추기 위해 운영 DB trigger가 다른 테이블을 직접 갱신하고 있었습니다. 평소의 작은 변경은 단순하게 처리할 수 있었지만, 대량 상품 업데이트에서는 같은 트랜잭션 안의 작업이 커지며 RDS Lock과 운영 부담을 만들었습니다.
실시간 변경과 대량 재생성을 같은 경로로 처리하면 한쪽의 부하가 다른 쪽의 안정성을 해칩니다. 원본 데이터의 쓰기 성공 여부가 검색 데이터 갱신에 지나치게 결합되어 있었고, 실패했을 때 어떤 이벤트가 누락됐는지 확인하고 다시 처리하기도 어려웠습니다.
무엇을 확인했는가
trigger 유지, 애플리케이션 이벤트, polling과 CDC를 포함한 네 가지 대안을 비교했습니다. 판단 기준은 원본 트랜잭션과의 결합도, 변경 지연, 대량 작업의 제어 가능성, 기존 코드 변경 범위와 실패 후 복구 가능성이었습니다.
또한 실시간 이벤트만 옮긴다고 문제가 끝나지 않았습니다. 초기 데이터와 대량 수정에는 별도의 backfill 경로가 필요했고, 이벤트 순서·중복·누락과 Worker 실패를 운영자가 관측할 수 있어야 했습니다. 영향을 받는 데이터 수에 따라 실시간 처리와 대량 처리를 나눌 기준도 필요했습니다.
어떤 선택을 했는가
팀 논의를 거쳐 RDS logical replication과 AWS DMS로 변경을 읽고, Kinesis와 Lambda Worker가 검색 데이터를 갱신하는 CDC 구조를 선택했습니다. 아키텍처 선택은 공동 결정이었고, 저는 대안 비교와 DMS·Kinesis·Lambda·backfill 인프라, IAM과 네트워크 구성을 담당했습니다.
영향 범위가 작은 변경은 이벤트로 처리하고, 300개 이상을 바꾸는 작업은 실시간 경로에 몰아넣지 않고 200개 단위의 backfill로 분리했습니다. trigger는 전환 중의 fallback으로 유지하고, 수동 재처리와 알림을 복구 경로로 마련했습니다.
어떻게 전환하고 검증했는가
staging에서 logical replication, DMS task, stream과 Worker 연결을 확인한 뒤 실제 변경 이벤트가 검색 데이터에 반영되는지 비교했습니다. 대량 변경은 별도 backfill로 실행하고 처리 단위마다 결과를 검증했습니다.
전환 과정에서 누락된 insert 18건을 찾아 보완했고, DMS 메모리 부족으로 task가 중단되는 문제도 조정했습니다. DMS task 실패와 대량 CDC 발생을 Slack으로 알리도록 해 무음 실패를 줄였습니다. 실시간 처리, backfill과 복구 경로를 함께 검증한 뒤 production에 배포했습니다.
이후 무엇이 달라졌는가
원본 DB의 대량 update가 검색 데이터 동기화까지 같은 트랜잭션에서 떠안던 구조를 분리했습니다. 작은 변경은 CDC로 이어지고, 큰 변경은 제어 가능한 크기의 backfill로 처리되어 운영 부하와 복구 범위를 나눌 수 있게 됐습니다.
파이프라인 실패를 task 상태와 Slack 알림으로 확인하고, 누락이나 오류가 있을 때 수동 재처리할 수 있는 경로도 생겼습니다. 특정 기술을 도입한 것보다 실시간성, 대량 처리와 복구 가능성을 서로 다른 경로로 다룬 것이 핵심 변화였습니다.
다시 한다면
이벤트에 멱등성 키와 처리 상태를 더 명시적으로 두고, 원본 변경 수와 최종 반영 수를 자동 비교하는 정합성 대시보드를 초기부터 만들겠습니다. backfill과 실시간 이벤트가 같은 데이터를 만날 때의 우선순위도 실행 절차가 아니라 데이터 계약으로 고정하겠습니다.
CDC 인프라는 애플리케이션 코드 밖의 실패 지점이 많습니다. DMS 메모리, stream 지연, Worker 오류와 최종 데이터 차이를 하나의 관측 흐름으로 연결해 운영자가 어느 단계에서 멈췄는지 더 빠르게 찾을 수 있게 하겠습니다.