Debezium 에 대해 알아보자

goyo·2026년 5월 27일

1. Debezium 이란?

| 데이터베이스의 변경 사항을 실시간으로 감지하고 스트리밍해주는 오픈소스 CDC 플랫폼

  • 기존에는 데이터베이스의 데이터가 변경사항이 있는지 확인하기 위해 주기적으로 쿼리를 날리는 Polling 방식을 썼으나, Debezium 은 데이터베이스의 트랜잭션 로그를 직접 읽는 로그 기반 CDC 방식을 사용함

  • 성공적으로 commit 이 발생한 데이터에 대해서만 변경사항이 전파되기 때문에 실패한 트랜잭션은 고려할 필요가 없음

  • Debezium 은 변경사항을 디스크에 저장하기때문에 데이터의 변경사항을 전달받아야하는 애플리케이션이 다운되더라도 문제가 없음


2. 데이터 ETL 방식과 CDC 의 필요성

  1. M: 모든 데이터에 대해서 전체 적재(전체 데이터 Overwrite) 를 통해 변경사항이 전부 반영된 최신의 데이터를 가져옴

  2. HI: INSERT 만 되는 테이블의 성격에 해당하며, 날짜를 기준으로 증분 데이터만 가져옴

  3. HIU: INSERT 혹은 UPDATE 되는 테이블 성격에 해당하며 날짜를 기준으로 최신 데이터(증분 데이터) 가져옴

이 3가지 모두 쿼리로 적용가능하지만 삭제된 데이터를 반영할 수 있는 것은 M 밖에 없음
하지만 데이터가 수억 건 이상으로 넘어가게 된다면, index scan 도 의미없는 full scan 특성상 운영DB 에 엄청난 부하가 가게 될 것이고, 시간과 비용 또한 무시 못하게 됨
결국 삭제를 감지하여 반영할 수 있는 방법이 필요한데 이 때 CDC 를 구현하게 됨


3. 로그 기반의 CDC 의 장점

  1. 낮은 오버헤드 : 주기적으로 SELECT 쿼리를 날리지않으므로 데이터베이스 CPU 에 부담을 주지않고 실시간에 가까운 처리가 가능함

  2. 데이터 유실 없음: 데이터베이스에 기록되는 모든 로우 레벨 변경 사항을 추적하므로, 사소한 변경이나 삭제 이벤트까지 완벽하게 잡아냄

  3. 애플리케이션 변경 최소화: 변경 감지를 위해 테이블에 변경 시각 타임스탬프 컬럼이나 트리거를 강제로 추가할 필요가 없음


4. Debezium 아키텍처 방식 비교

분류① Kafka Connect 방식 (표준)② Debezium Server 방식 (독립형)③ Debezium Embedded 방식 (내장형)
구조Kafka 분산 클러스터 위에서 동작별도의 단독 프로세스(App)로 구동자바 애플리케이션의 라이브러리로 포함
Kafka 필수 여부필수없어도 됨없어도 됨
이벤트 목적지 (Sink)Kafka TopicAWS Kinesis, RabbitMQ, Pub/Sub, Webhook, Redis 등자바 코드 내부 인메모리 버퍼 (Consumer)
장점고가용성(HA), 대규모 스케일아웃, 검증된 안정성카프카 없이 가볍게 다양한 클라우드 큐로 전송 가능인프라 추가 부담 제로, 가장 가볍고 제어가 자유로움
단점카프카 클러스터 관리 비용 및 높은 인프라 복잡도클러스터링(분산 처리) 미지원, 이중화 구현이 까다로움애플리케이션 종료 시 이벤트 유실 위험, 로직 직접 구현

5. Debezium 기능

  • Snapshot: Debezium이 source database와 처음으로 연결됐거나 또는 모든 로그가 존재하지 않을 경우 활용하는 방식
  • Filters: schema, table, column 별로 필터링 여부를 결정
  • Masking: 특정 컬럼의 데이터를 masking 할 수 있음, 민감한 데이터(예를 들어 개인정보)를 취급할 때 유용한 기능
  • Monitoring: JMX를 통해 connector을 모니터링
  • Message transformation: 메시지를 수정할 수 있는 기능

6. Snapshot Mode

1) Snapshot 이란?

Debezium 이 처음 시작될 때, 대상 테이블의 초기 상태(정적 데이터)를 한번 가져오는 작업

  • DB 데이블 전체를 스캔하여 SELECT 로 가져옴 (단발성 full scan snapshot)
  • 이후 binlog만 지속적으로 tailing
  • "전체 테이블의 초기 상태" + "이후 변경사항(CDC)" 을 함께 추적해야 정합성있는 데이터 스트림을 kafka 에 보낼 수 있으므로 스냅샷을 가져온 이후에 이후의 변경사항들에 대해서 변경 로그로 확인

2) Snapshot Mode 종류

initial (기본값) : 처음 시작 시 전체 테이블을 스냅샷, 이후 binlog 로 계속 tailing
schema_only : 테이블 구조만 가져오고 데이터는 snapshot 안함 (단 binlog 는 계속 읽음)
initial_only : 최초 snapshot 만 수행, binlog 는 tailing 안함 (일회성 추출 목적)
never : snapshot,binlog 안 읽음 (기존 offset 기준부터만 tailing)
when_needed: Debezium 이 판단해서 snapshot 수행 여부 결정 (특정 커넥터 지원)


7. 부하 가능성 및 요소

1) 운영에서의 부하 가능성

  • DB 에 초기 설정시에 snapshot 을 찍는(full scan) 을 해야 할 일이 생기고, 이는 운영 DB 에 부하를 줄 수 있음
    • 대량 row SELECT → DB의 디스크 I/O,CPU 자원 사용
    • 병렬성 없이 단일 커넥터에서 수행되면 느림
  • 다만 대량의 처리가 아닌 이후의 변경 로그만 읽어오는 경우라면 CPU 의 부하가 크지 않음

2) 부하 관련 요소

항목영향설명
Snapshot 테이블 크기CPU, Disk I/O큰 테이블 SELECT는 I/O와 CPU 모두 부담
binlog 크기 (offset 이후)CPU, Memory오래된 binlog를 순차 처리하므로 CPU 부하 증가 가능
CDC consumer 처리 속도Kafka backlogDebezium이 빨리 밀어도 Kafka나 downstream이 느리면 부하 쌓임
Debezium 인스턴스 리소스Memory, GCJVM 메모리 부족 시 GC 폭증 및 OOM 발생 가능

3) Snapshot 이 다시 실행되는 경우

Debezium 재시작 시 흐름

  1. 커넥터 시작
  2. kafka offset 저장소 확인
  3. 이전 snapshot 이 완료되었고, binlog 위치도 있다면 snapshot 건너뜀
  4. 저장된 binlog 위치부터 log-based CDC 수행

4) 시나리오별 원인

  • offset.storage.topic 데이터가 사라졌거나 초기화됨: Debezium 은 이전 상태를 알 수 없게 되므로 snapshot 을 다시 수행
  • Kafka Connect의 connector name 이 바뀜: offset이 새로운 이름(key)으로 저장되므로, 새로운 커넥터로 인식되어 snapshot 을 다시 수행
  • snapshot.mode=always 로 명시: 매번 시작할 때마다 snapshot 을 강제로 수행하도록 설정된 상태
  • 커넥터 구성 변경 (database.hostname, database.server.name 등): 내부적으로 새로운 connector 로 인식되어 snapshot 이 재시작될 수 있음
  • pod 가 ephemeral 하고, offset 을 Kafka 가 아닌 로컬에 저장했을 경우: 재시작 시 로컬에 있던 offset 정보가 유실되므로 snapshot 이 재시작될 가능성이 매우 높음

5) 안전한 운영을 위한 고려 요소

항목권장 설정 / 전략
Offset 저장 방식offset.storage.topic을 로컬이 아닌 Kafka 내부 토픽으로 설정
Connector name동일한 이름 유지 (connector 이름 변경 시 새로운 snapshot 유발)
Snapshot Mode의도치 않은 재시작 시 snapshot을 방지하려면 snapshot.modeschema_only 또는 never로 설정 고려
Offset 백업필요 시 주기적으로 offset 토픽 백업 (Kafka MirrorMaker 등 활용)
Connector 배포 시 주의Helm/Manifest로 connector 배포 시 매번 생성-삭제(Lifecycle)되지 않도록 주의


* Optional

SMT(Single Message Transformation)

DB 에서 캡처한 메시지를 토픽에 저장하기 직전에 변형,가공 하는 기능

  • 데이터 구조 단순화 (ExtractNewRecordState)
    • 복잡한 메타데이터와 before 상태 제거 및 최종 변경된 after 데이터만 추출하여 토픽에 저장 가능
{
	"name": "mysql-debeizum-connector",
    "config": {
    	"connector.class": io.debezium.connector.mysql.MySqlConnector",
        "task.max": "1",
    
    // --- SMT ExtractNewRecordState 설정 ---
    // 별칭을 설정함
    "transforms": "unwrap",
    
    //별칭이 어떤 Java 클래스를 사용할지 지정
    "transforms.unwrap.type":"io.debezium.transforms.ExtractNewRecordState",
    
    // 만약 op : DELETE 일 때 토픽에 null 메시지를 보낼지 여부  
    "transforms.unwrap.drop.tombstones": "true",
    
    // 테이블 삭제 시 동작 여부
    "transforms.unwrap.delete.handling.mode": "drop"
    }
}

  • 이벤트 필터링 (Filter)
    • 특정 조건에 맞는 데이터만 토픽으로 보내고 나머지는 버릴 수 있음(예: status == 'COMPLETED' 만 통과시키는 의도)
{
  "name": "postgres-debezium-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    
    // --- SMT Filter 설정 ---
    "transforms": "filter",
    
    // 필터 변환 클래스 지정
    "transforms.filter.type": "io.debezium.embedded.Transform$Filter",
    
    // 표현식 언어로 JSR-223(JavaScript) 사용
    "transforms.filter.language": "jsr223.groovy",
    
    // 필터링 조건 메서드 (예: 'status' 컬럼 값이 'COMPLETED'인 데이터만 통과시킴)
    // 아래 조건이 'true'를 반환하는 이벤트만 카프카에 적재
    "transforms.filter.condition": "value.after?.status == 'COMPLETED'"
  }
}

Reference
https://debezium.io
https://spidyweb.tistory.com/604

0개의 댓글