작업 완료 · 2026

파일 기반 배치형 CDC와 멱등 UPSERT

파일 단위 binlog를 직접 파싱하고, 정상 변환된 DML을 멱등 UPSERT로 적용하도록 바꿨습니다.

전달 단위ROW-format binlog 배치 파일
소속래브라도랩스(LabradorLabs)
역할Data Engineer · CDC 전환 제안 및 설계·구현
GoCDCUPSERTBinary Log

작업 요약

파일당 처리 속도 평균 2.5배 · 최대 5배

재시도를 멱등하게 만든 이유

레거시 동기화의 단위는 binlog 파일 전체였습니다. 파일 안의 이벤트 하나가 실패해도 파일 전체가 막히고, 적용된 범위는 stderr 텍스트를 세어 추정해야 했기 때문에 정확한 복구 위치를 찾기 어려웠습니다. 품질 개선 회의에서 CDC 구조 전환을 직접 제안한 이유입니다.

정상 변환된 INSERT·UPDATE에 한해 UPSERT로 적용했습니다. DELETE·DDL과 truncation skip은 이 보장에 포함하지 않았으며, 파일 전체를 데이터 손실 없이 재실행할 수 있다는 보장은 없습니다.

배경

레거시(v2/v3) Updater는 mysqlbinlog 유틸리티를 파이프로 실행해 binlog를 대상 DB에 그대로 적용하는 방식이었습니다. SQL을 제어할 수 없으니 중복 키 에러가 나면 수동 개입이 필요했고, DEFINER 절·Virtual Column처럼 고객사 환경에서 깨지는 구문도 거를 수 없었습니다. 일부 고객사는 MySQL replica 방식의 상시 TCP 연결을 허용하지 않아, 기존 HTTPS 파일 배포 경계를 유지한 채 변경분을 전달해야 하는 제약도 있었습니다.

Before

파일 단위 All-or-Nothing 리플레이 → 이벤트 하나의 실패가 파일 전체를 막음, 중복 적용 시 에러, 복구 위치 추적 불가

After

배치 binlog 파일 → Go Updater 오프라인 파싱 → 정상 변환된 INSERT·UPDATE를 UPSERT로 적용해 재실행 시 중복 반영 방지

한 일

아키텍처 (데이터 흐름)

전체 구조를 먼저 보고, 크게 열어 세부 내용을 확인하세요.크게 보기ExcalidrawMermaid
배포 DB와 FastAPI 서버에서 고객사 Go Updater로 암호화한 HTTPS 배치 파일을 전달하고, 검증·복호화와 파싱 뒤 정상 변환된 INSERT·UPDATE를 UPSERT로 반영하는 구조
Go Updater는 암호화된 배치 파일을 검증·복호화한 뒤 파싱하고, 정상 변환된 INSERT·UPDATE를 UPSERT로 적용합니다. DELETE·DDL과 건너뛴 오류 데이터는 멱등 재실행 보장에 포함하지 않습니다.

파일 배포 경계를 바꾸지 않은 채 Go Updater의 오프라인 파싱과 DML 변환을 적용했습니다. 재실행 안전성은 정상 변환된 INSERT·UPDATE 범위이며, truncation skip은 별도 정합성 확인이 필요합니다.

결과

재실행 범위정상 변환된 INSERT·UPDATE는 UPSERT로 중복 반영을 방지
운영 인계설계·구현과 배포 시나리오 리뷰 뒤 고객사 배포·운영은 기술지원팀에 이관
적용 후 관찰2026년 9월 확인: 고객사 27곳 중 약 절반이 새 버전으로 전환했으며, 전환 후 5~6개월 동안 해당 고객사에서 확인된 정합성 이슈는 0건
추가 확인truncation skip은 건너뛴 데이터가 있어 후속 정합성 확인이 필요

역할

파일 단위 동기화의 한계를 검토해 CDC 구조 전환을 제안하고 설계·구현과 배포 시나리오 리뷰를 마친 뒤, 고객사 배포는 기술지원팀에 이관했습니다. 도구 선정 단계에서 Maxwell은 FileSink PoC로 DML·DDL JSON 출력을 확인했지만, 공식 MySQL sink가 없고 MySQL 8.4의 ZSTD 압축 Transaction_payload를 처리하지 못해 제외했습니다. HTTPS 파일 전달 방식은 유지하면서, 기존 난독화를 AES-256-GCM 암호화와 수신 측 검증으로 바꿨습니다. 기술지원팀은 고객사 현장 배포와 일상 운영을 맡고, 저는 운영 중 접수된 이슈를 재현해 구현을 개선하고 기술 지원을 제공했습니다.

근거 자료

아래 기록에 근거해 정리했습니다. 내부 원문 경로를 표시하며, 비공개 원문 파일은 이 페이지에서 제공하지 않습니다.