데이터베이스의 심장 소리를 듣다: 변경 데이터 캡처(CDC)
출처: Dev.to
CDC는 변경 데이터 캡처(CDC)를 의미합니다.
학습할 내용
- CDC가 무엇인지
- 그 배경 이야기
- 내부 작동 방식
- 일반적인 사용 사례
- 간단한 구현 예시
CDC란 무엇인가?
변경 데이터 캡처(CDC)는 데이터를 수정하고 그 변화를 외부 시스템에 노출하는 기술입니다.
반복적으로 데이터베이스를 쿼리하여 변경 사항을 확인하는 대신, CDC는 삽입, 업데이트, 삭제가 발생하는 즉시 애플리케이션이 스트림으로 해당 변화를 소비하도록 합니다.
CDC를 데이터베이스의 심장 소리를 듣는 방식으로 생각하면 됩니다.
데이터가 매번 변경될 때마다 데이터베이스는 내부적으로 해당 변경을 기록합니다. CDC는 이러한 변화를 다른 시스템이 실시간으로 반응할 수 있게 노출합니다.
CDC 배경 이야기
CDC를 이해하려면 데이터베이스가 수십 년간 어떻게 작동해 왔는지 이해하는 것이 도움이 됩니다.
데이터가 변경될 때마다 데이터베이스는 단순히 이전 값을 덮어쓰고 넘어가지 않습니다. 대신 발생한 작업을 내부 기록으로 유지합니다.
이 기록들은 일반적으로 트랜잭션 로그에 저장됩니다.
- 데이터베이스에 수행된 모든 변경을 기록
- 장애 복구
- 다른 노드로 데이터 복제
- 일관성 유지
삽입, 업데이트, 삭제 작업마다 로그 항목이 생성됩니다.
이 항목들은 고유한 위치 또는 토큰으로 순서화되고 식별됩니다.
정렬은 필수적입니다.
다음 시퀀스를 상상해 보세요:
- 사용자 생성
- 사용자 업데이트
- 사용자 삭제
복제가 이러한 작업을 다른 순서로 적용하면 완전히 다른 데이터를 얻게 됩니다.
이 로그들은 순서가 보장되므로 데이터베이스는 변경 사항을 신뢰할 수 있게 재생하고 시간이 지나면서 상태를 재구성할 수 있습니다.
이것이 많은 데이터베이스 시스템에서 복제의 작동 방식입니다.
복제본은 일반적으로 초기 스냅샷을 시작으로 트랜잭션 로그를 재생하며 새로운 변경을 지속적으로 적용합니다.
CDC가 어떻게 활용되는가?
원래 이러한 로그는 데이터베이스 자체를 위한 것이었습니다.
CDC는 이 아이디어를 확장하여 외부 애플리케이션이 동일한 변화를 소비하도록 합니다.
복제본만 데이터베이스 변경을 읽는 것이 아니라, 여러분의 애플리케이션도 이를 읽을 수 있습니다.
데이터가 변경될 때마다 상시 쿼리를 수행하지 않고 즉시 반응할 수 있습니다.
외부 시스템이 신뢰ably(신뢰) 소비할 수 있는 순서가 보장된 데이터베이스 변경 스트림을 노출하는 것이 핵심 아이디어입니다.
CDC 작동 방식
다양한 데이터베이스는 CDC를 구현 방식이 다르지만 개념 자체는 동일합니다.
몽고DB
몽고DB는 변경 스트림(Change Streams)을 통해 CDC를 제공합니다.
각 이벤트에는 재개 토큰(resume token)이 포함되어 있어, 중단 또는 실패 후 마지막으로 처리한 변경점에서 계속 읽을 수 있습니다.
MySQL
MySQL은 자신의 **바이너리 로그(Binlog)**를 통해 변화를 노출합니다.
CDC 도구는 binlog를 읽어 데이터베이스 작업을 이벤트로 변환할 수 있습니다.
PostgreSQL
PostgreSQL은 논리 디코딩(Logical Decoding)과 논리 복제(Logical Replication)를 통해 CDC를 제공합니다.
이 메커니즘들은 애플리케이션이 순서대로 데이터베이스 변화를 소비하도록 허용합니다.
구현 방식은 다르지만 모두 동일한 기능을 제공합니다:
데이터베이스 변경의 순서가 보장된 스트림.
CDC는 대체로 풀 기반이다
흔히 있는 오해는 데이터베이스가 직접 여러분의 애플리케이션에 변경을 푸시한다는 것입니다.
실제로 대부분의 CDC 구현은 근본적으로 풀(요청) 방식입니다.
소비자는 데이터베이스에서 다음 사용 가능한 변경을 요청합니다.
하지만 애플리케이션은 보통 장기 연결 또는 커서를 유지하여 푸시 이벤트를 받는 것과 유사한 느낌을 줍니다.
예를 들어, MongoDB의watch()API는 스트림을 열어두고 변경 사항이 발생할 때마다 새로운 이벤트를 지속적으로 전달합니다.
애플리케이션 관점에서는 실시간으로 느껴집니다.
간단한 CDC 예시
이 개념을 이해하려면 모든 데이터베이스 변경을 표준화된 이벤트로 변환한다고 상상하면 됩니다.
function captureDataChange($operation, $table, $id, $before, $after) {
$cdcEvent = [
"metadata" => ["operation" => $operation,
"table" => $table,
"id" => $id],
"before" => $before,
"after" => $after
];
echo "Streaming event: " . json_encode($cdcEvent) . PHP_EOL;
}
captureDataChange(
"UPDATE",
"users",
42,
["name" => "Alice", "role" => "Developer"],
["name" => "Alice", "role" => "Architect"]
);
Output:
{
"metadata": {
"operation": "UPDATE",
"table": "users",
"id": 42
},
"before": {
"name": "Alice",
"role": "Developer"
},
"after": {
"name": "Alice",
"role": "Architect"
}
}
Enter fullscreen mode
Exit fullscreen mode
CDC 대 전통적 폴링
Without CDC, applications often use polling.
SELECT *
FROM orders
WHERE updated_ at > :last_ seen_timestamp;
This approach works, but it has drawbacks:
- 데이터베이스에 추가 부하
- 규모에 따른 비용이 비싼 쿼리
- 업데이트 누락 가능성
- 중복 처리 로직
CDC는 데이터베이스 변경 스트림에서 직접 변경을 소비함으로써 이러한 문제를 피합니다.
Instead of repeatedly asking: “변경 사항이 있나요?” the database tells you: “이것이 변동 내용입니다.”
CDC가 왜 중요한가?
CDC는 단순한 데이터베이스 기능을 넘어서기 때문에 건축 블록 역할을 합니다.
데이터베이스 변화가 이벤트가 되면서 새로운 가능성이 나타납니다.
- 검색 인덱스 동기화 (Elasticsearch/OpenSearch)
- 분석 파이프라인
- 이벤트 기반 아키텍처
- 캐시 무효화
- 감사 트레일
- 데이터 웨어하우스 동기화
- 머티리얼라이즈드 뷰 구축
- 서비스 간 데이터 동기화
예를 들어, 제품이 데이터베이스에 업데이트될 때 CDC 소비자는 자동으로 다음을 업데이트합니다:
- 검색 인덱스
- 캐시
- 보고 시스템
- 추천 엔진
원본 애플리케이션에 수정 없이.
현대 아키텍처에서의 CDC
많은 조직은 Debezium과 같은 CDC 플랫폼을 사용해 다양한 데이터베이스에서 변화를 통합적으로 소비합니다.
이 플랫폼들은 종종 CDC 이벤트를 Apache Kafka와 같은 시스템에 게시하여 여러 소비자가 동일한 스트림을 독립적으로 처리할 수 있게 합니다.
이로 인해 CDC는 현대적인 이벤트 기반 시스템에서 핵심 건축 블록이 됩니다.
최종 생각
핵심적으로, CDC는 간단한 아이디어입니다:
데이터베이스 변경은 이미 어딘가에 기록되어 있습니다.
CDC는 외부 시스템이 해당 변화를 청취하도록 허용합니다.
MongoDB Change Streams, MySQL Binlogs, 또는 PostgreSQL Logical Replication을 사용하든 원리 자체는 동일합니다:
신뢰할 수 있는 순서가 보장된 데이터베이스 변경 스트림.
Once you start viewing database updates as events rather than rows being modified, CDC becomes one of the most powerful tools for building scalable and loosely coupled systems.
데이터베이스 업데이트를 행(row)으로 수정하는 것이 아니라 이벤트로서 보기 시작하면 CDC는 스케일링 및 느슨한 결합성을 구축하는 데 가장 강력한 도구 중 하나가 됩니다.