티스토리 뷰
지난 글에서 우리가 CDC 파이프라인을 JDBC source connector로 구축한 얘기를 했다. 동기화하면서 비정규화 변환까지 함께 처리할 수 있어서 우리 요구사항에 잘 맞는 도구였다.
근데 솔직히 그 글에서 못 한 얘기가 있다. 이 도구의 가장 큰 약점은 스키마 변경에 약하다는 거다. 운영하면서 이거 때문에 진짜 자주 깨졌다. 오늘은 그 얘기를 좀 해보려고 한다.
평일 오후 3시, 슬랙에 빨간 알림
상황은 대충 이렇다. 평화롭게 동기화 잘 되던 평일 오후, 슬랙에 알림이 뜬다.
🚨 connector
user_activity_martFAILED. config 백업 후 재시작 시도.
뭐 알아서 재시작되겠지 싶다. 10분 주기로 FAILED 감지하면 자동 재시작하는 로직을 돌리고 있으니까.
10분 뒤. 다시 FAILED.
또 10분 뒤. 다시 FAILED.
이쯤 되면 안다. 자동 재시작으로 못 푸는 케이스라는 걸.

JDBC source connector 동작을 다시 보자
뭐가 문제인지 보려면 이 커넥터가 어떻게 도는지부터 봐야 한다. 어렵진 않다.
설정된 SQL 쿼리 → 주기적으로 운영 DB에 실행 → 결과를 Kafka 토픽으로 publish
여기서 핵심은 토픽의 스키마다. 처음 커넥터를 등록할 때, 쿼리 결과 컬럼을 기반으로 토픽 스키마가 정해진다. user_id(INT), country_code(STRING), message_count(INT) 같은 식.
이 토픽을 컨슘하는 측(우리 환경에선 Kafka Connect의 sink 측, 분석 DB로 적재하는 곳)도 같은 스키마를 기대한다.
여기서 운영 DB의 컬럼이 바뀌면?
우리가 부딪힌 케이스들
케이스 1: 신규 컬럼 추가. 비즈니스 백엔드에서 users 테이블에 subscription_tier라는 컬럼이 추가됐다. 이 컬럼이 JDBC source connector 쿼리에 포함되도록 SQL이 업데이트됐다. 이제 토픽엔 신규 컬럼이 있는데 sink 쪽 테이블엔 없다. 컨슈머 측에서 "어 이 컬럼 어디 넣어?" 하다가 FAILED.
케이스 2: 컬럼 타입 변경. amount 컬럼이 INT에서 BIGINT로 바뀌었다. 토픽 스키마가 깨진다. 컨슈머가 받은 데이터를 기존 INT 컬럼에 넣으려다 오버플로우.
케이스 3: 컬럼 삭제 또는 이름 변경. SQL 쿼리 자체가 깨진다. SELECT ... FROM users 했는데 name 컬럼이 사라졌다. 쿼리 실패. 커넥터 FAILED.
케이스 4: 제일 짜증나는 케이스. 한쪽만 바뀌는 경우다. 운영 DB는 바뀌었는데 sink 쪽 테이블은 그대로일 때다. 양쪽이 어긋난 채로 며칠 가다가, 누군가 분석 쿼리 돌리면서 "어 이 컬럼 왜 다 NULL이지?" 하고 발견한다.
우리의 대응 방법: 수동 DDL
부끄럽지만 우리 방식은 단순하다. 사람이 직접 간다.
- 슬랙 알림 받음. 자동 재시작이 무한 실패하는 거 확인.
- 운영 DB 스키마 변경 사항 확인 (보통 PR 히스토리 뒤짐).
- sink 측 테이블에 같은 변경을 DDL로 적용.
- JDBC source connector의 SQL을 업데이트 (필요하면).
- 커넥터 재시작.
- 데이터 정합성 검증.
사이드 이펙트 없이 끝나면 평균 30분에서 1시간 정도 걸린다.
왜 자동화 안 하냐고? 자동 복구는 "상태 회복"만 가능해서다. config가 꼬여서 죽은 거면 백업 → 재기동으로 풀리지만, 스키마 불일치는 회복할 상태가 없다. 양쪽 스키마 중 어느 쪽이 맞는지를 사람이 정해줘야 한다.
그래서 결국 우리한테 필요한 건 사전 차단
운영해보면 안다. 사고 난 다음에 빨리 복구하는 것보다 사고 자체를 막는 게 훨씬 싸게 먹힌다는 것. 30분 복구도 그 자체로 시간이지만, 그 사이 분석 데이터가 텅 비어버리는 게 더 큰 문제다.
지금 우리가 하는 사전 조치:
- 운영 DB 스키마 변경 PR에
[data-pipeline]라벨 달기 → 데이터 인프라 담당자가 자동 알림 받음 - sink 측에 영향 가는 변경은 PR 머지 전에 동기화 작업 우선 진행
- 신규 컬럼이면 sink 측에 먼저 추가 → 운영 DB에 추가 (역순)
근데 이게 100% 되진 않는다. 사람이 까먹기도 하고, 긴급 핫픽스로 라벨 달 시간 없을 때도 있다. 그래서 결국 사고는 난다. 그래도 이걸 도입하고 나서 빈도는 확실히 줄었다.
Debezium의 schema registry 접근
하나 짚고 가고 싶은 게 있다. Debezium은 이 문제를 좀 다르게 푼다.
Debezium은 보통 Schema Registry라는 별도 컴포넌트와 함께 쓴다. Avro나 Protobuf 같은 스키마 정의 시스템을 두고, 모든 메시지는 스키마 ID와 함께 publish된다. Producer는 스키마 등록 → Consumer는 스키마 ID로 조회 → 둘이 호환되는지 확인.
호환이 안 맞으면? 설정에 따라 publish 자체가 막히거나 명확한 에러로 떨어진다. "몰래 깨지는" 일이 없다.
솔직히 이게 제일 부럽다. 우리 환경에선 스키마가 바뀌었는지를 사고 나고 나서야 안다. Debezium + Schema Registry 환경이면 바뀌는 시점에 바로 알 수 있다.
다만 Schema Registry를 운영하려면 별도 인프라가 필요한데, 우리 회사 상황에선 그것까지 도입할 인력 여유가 없었다. 그래서 일단은 사람이 라벨 달고 사전 조치하는 방식으로 버티고 있다.
한번 정리해보면 이렇다.
- Schema Registry는 진짜 도입하고 싶다. 일단 스키마 호환성 체크가 자동화되면 휴먼 에러가 한 단계 차단된다.
- PR 라벨 같은 휴먼 시스템은 임시방편이라는 걸 인정해야 한다. 안 까먹을 수 있는 사람은 없다. 사람이 까먹는 걸 전제로 시스템을 설계해야 한다.
- Sink 측 스키마 자동 마이그레이션도 고민할 만하다. Source 스키마가 바뀌면 sink 쪽에 컬럼 추가까지 자동으로 해주는 식. 컬럼 삭제까진 위험해서 못 건드리겠지만.
스키마 변경 때문에 부서지는 건 JDBC source connector를 쓰는 한 계속될 거 같다. 도구가 가진 한계니까. 다만 그 한계를 알고 운영하는 거랑 모르고 깨지는 건 다르다. 사고 시간을 1시간에서 30분으로 줄이고, 빈도를 주 1회에서 월 1회로 줄이는 정도가 지금 우리가 할 수 있는 일이다.
다음 글에선 RDB에서 S3 + Athena로 전환했을 때 비용을 어떻게 계산했고 어디서 얼마나 아꼈는지 한번 풀어볼까 한다.
'데이터 엔지니어링' 카테고리의 다른 글
| RDB에서 S3 + Athena로 전환할 때, 비용을 어떻게 계산했나 (0) | 2026.05.13 |
|---|---|
| JDBC Source Connector로 CDC 파이프라인을 구축한 이야기 (0) | 2026.05.13 |
- Total
- Today
- Yesterday
- DataFramebool
- jdbc
- Haiku4096토큰
- 5중검증
- CryptoBot
- 메이저화이트리스트
- Kafka
- 코인별손익분석
- 데이터엔지니어링
- P0P4우선순위
- AnthropicCaching
- Page_DownPage_DownPage_Down
- 일일주간월간스케줄러
- 트레일링스탑버그
- CDC
- SlidingWindowTTL
- 한달운영진단
- LLM비용오차
- LLM파라미터머지
- 비용80%절감
- 코인별전략배정
- kafka connect
- 일경계처리
- 코드자체감사
- 데모모드
- BOJ #JS
- Telegram알림
- LLM비활성결정
- 수수료슬리피지
- LLM동적호출
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |