> ## Documentation Index
> Fetch the complete documentation index at: https://www.integrate.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# ETL: CDC Database Source로 변경 데이터만 효율적으로 처리

> Integrate.io ETL의 CDC Database Source 컴포넌트를 사용해 변경된 데이터만 효율적으로 처리하는 방법을 설명합니다.

## 시작하며

데이터 파이프라인 운영에서 자주 겪는 문제는 "매번 테이블 전체를 처리하는 것은 비효율적이다"라는 점입니다. Integrate.io의 **CDC(Change Data Capture) Database Source**는 이전 실행 시점부터의 차분 데이터만 감지하여, 추가·업데이트 레코드(Upsert)와 삭제 레코드(Delete)를 분리하여 출력합니다.

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-1.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=81f6a92baae9d3b9e9478f8c88a67ab3" alt="onpremise-part02-ko image 1" width="417" height="1076" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-1.webp" />
</Frame>

## CDC Database Source의 기본 동작 원리

스냅샷 비교 방식을 채택합니다. 파이프라인 실행 시 소스 테이블의 현재 상태를 이전에 저장한 스냅샷과 비교하여 차분을 감지합니다.

**2가지 출력:**

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-2.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=51f62e5073a04e6ff2cab9c61751bc07" alt="onpremise-part02-ko image 2" width="667" height="437" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-2.webp" />
</Frame>

* **Upserted records(추가·업데이트 레코드)**: 이전 스냅샷에 없던 새로운 행, 또는 값이 변경된 기존 행
* **Deleted records(삭제 레코드)**: 이전 스냅샷에는 존재하지만, 현재 테이블에는 없는 행

동작 흐름:

1. 현재 테이블과 스냅샷을 기본 키(Primary Key)로 대조
2. 현재 테이블에만 있는 행 → 신규 레코드(Upserted)
3. 양쪽에 존재하지만 값이 변경된 행 → 업데이트 레코드(Upserted)
4. 스냅샷에만 있는 행 → 삭제 레코드(Deleted)

초회 실행 시에는 모든 레코드가 Upserted로 출력됩니다.

## CDC Source에서 알아야 할 개념

### 1. 스냅샷 저장 방식: File Based와 Database

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-3.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=e231c70636259f937e5e53cb2c9584ac" alt="onpremise-part02-ko image 3" width="1055" height="880" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-3.webp" />
</Frame>

| 연결 유형      | File Based | Database |
| ---------- | ---------- | -------- |
| SQL Server | O          | O        |
| MySQL      | O          | X        |
| PostgreSQL | O          | X        |
| Snowflake  | O          | X        |
| 기타 DB      | O          | X        |

#### File Based 스토리지(전체 데이터베이스 대응)

Integrate.io가 관리하는 클라우드 스토리지에 Parquet 파일로 저장됩니다. 소스 데이터베이스에 대한 읽기 권한만으로 사용 가능합니다. S3 연결 설정 없이 자동으로 사용되며, 파이프라인 실행 성공 시 자동으로 덮어씁니다.

#### Database 스토리지(SQL Server 전용)

스냅샷을 소스 데이터베이스 내에 테이블로 저장합니다. 변경 감지 쿼리가 데이터베이스 내부에서 SQL로 실행되므로 처리 효율이 높습니다. 단, **SQL Server 전용**이며 쓰기 권한(`CREATE TABLE` 및 `INSERT` / `DELETE`)이 필요합니다.

스냅샷 테이블명 명명 규칙:

| 변경 감지 방식       | 스냅샷 테이블명                                 |
| -------------- | ---------------------------------------- |
| Primary Key    | `{테이블명}_integrate_io_snapshot`           |
| Composite Hash | `{테이블명}_integrate_io_snapshot_composite` |

SQL Server에서 쓰기 권한이 있는 경우 Database 스토리지를 선택하면 가장 효율적입니다. 그 외의 경우에는 File Based 스토리지를 선택하십시오.

### 2. 변경 감지 방식: Primary Key와 Composite Hash

#### Primary Key 방식

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-4.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=f5f867456c6760f27ab9185772c93ed0" alt="onpremise-part02-ko image 4" width="533" height="172" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-4.webp" />
</Frame>

테이블에 고유한 키 열(`id`, `customer_id`, `order_number` 등)이 있는 경우에 적합합니다. Change Detection Method에서 "Primary Key"를 선택하고 드롭다운에서 키 열을 선택합니다.

File Based 스토리지와 조합하는 경우, 기본 키 이외의 모든 열에서 **MD5 해시**가 자동 생성되어 행의 변경 여부를 효율적으로 판정합니다.

#### Composite Hash 방식

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-5.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=d568edabde19650969885da779200bdd" alt="onpremise-part02-ko image 5" width="557" height="204" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-5.webp" />
</Frame>

테이블에 신뢰할 수 있는 고유 키가 없는 경우나, 특정 열의 변경만 추적하고 싶은 경우에 적합합니다.

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-6.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=3e9445805a41b8c8a8d6d347cc41d9e0" alt="onpremise-part02-ko image 6" width="566" height="288" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-6.webp" />
</Frame>

| 옵션명                                       | 활성화         | 기능                                    |
| ----------------------------------------- | ----------- | ------------------------------------- |
| **Use custom columns for composite hash** | 체크박스        | 해시 생성에 사용할 열을 개별 지정. 체크 해제 시 모든 열을 사용 |
| **Composite key column**                  | 드롭다운(복수 선택) | 변경된 해시가 "업데이트"인지 "삭제+삽입"인지 구별하기 위한 열  |
| **Primary key(선택)**                       | 드롭다운        | 지정하면 업데이트와 삭제의 구별이 더 정확해짐             |

기본 키나 Composite key column을 지정하지 않으면, 해시값이 변경된 행이 Upserted와 Deleted **양쪽 출력**에 나타날 가능성이 있습니다.

### 소스 모드: Table 모드와 Query 모드

| 모드    | 대응 스토리지               | 사용 조건                                | 비고                               |
| ----- | --------------------- | ------------------------------------ | -------------------------------- |
| Table | Database / File Based | 단일 테이블 취득                            | 특별 조건 없음                         |
| Query | File Based만           | 복수 테이블 JOIN, 복잡한 WHERE 조건, 열 별칭 지정 등 | 쿼리 작성 후 **Refresh Fields** 클릭 필요 |

## 설정 절차 요약

1. 패키지 디자이너에서 **Database (CDC) Source** 컴포넌트를 추가하고 데이터베이스 연결을 선택

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-7.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=c7b7292dafa115bd643ccdaf60618e86" alt="onpremise-part02-ko image 7" width="1202" height="829" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-7.webp" />
</Frame>

2. 소스 모드 선택(Table 또는 Query)
   * Table 모드의 경우 스키마와 테이블을 선택

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-8.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=c21a9b5df18ff5dd60cdcd65f1b65185" alt="onpremise-part02-ko image 8" width="985" height="887" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-8.webp" />
</Frame>

* Query 모드의 경우 SQL 쿼리를 작성하고 **Refresh Fields**를 클릭

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-9.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=afdabe0e105284978f5b460555258965" alt="onpremise-part02-ko image 9" width="991" height="717" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-9.webp" />
</Frame>

3. 변경 감지 방식 선택(Primary Key 또는 Composite Hash) 및 감지 파라미터 설정

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-10.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=9180deba4c9ecfcbeaa00c3c145fef95" alt="onpremise-part02-ko image 10" width="976" height="352" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-10.webp" />
</Frame>

4. 선택 가능한 경우, 스냅샷 저장 방식 선택(Database 또는 File Based)

5. 하위 컴포넌트에 전달할 입력 열 선택

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-11.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=37d637a353c5ba77f84d52cf8f5b4392" alt="onpremise-part02-ko image 11" width="980" height="1000" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-11.webp" />
</Frame>

6. Upserted records 출력과 Deleted records 출력을 각각 적절한 대상(Destination) 또는 변환 컴포넌트에 연결

<Frame>
  <img src="https://mintcdn.com/integrateio/4uRSCv7RFYY0ghz9/images/korean-knowledge-base/onpremise-part02-ko/image-12.webp?fit=max&auto=format&n=4uRSCv7RFYY0ghz9&q=85&s=b68218fbd968aeb689728a53e54e3b34" alt="onpremise-part02-ko image 12" width="574" height="386" data-path="images/korean-knowledge-base/onpremise-part02-ko/image-12.webp" />
</Frame>

## 운영 시 모범 사례

### 1. 변경 감지 방식 선택 기준

신뢰할 수 있는 고유 키가 있는 경우 Primary Key 방식을 사용합니다. 고유 키가 없거나 키가 변경될 가능성이 있는 경우 Composite Hash 방식을 사용하십시오. Composite Hash 방식에서는 자주 변경되지만 업무적으로 중요하지 않은 열(예: `last_modified_timestamp`)을 해시 대상에서 제외하면 불필요한 차분 감지를 방지할 수 있습니다.

### 2. 스냅샷 저장 방식 선택 기준

SQL Server에서 쓰기 권한이 있고, 쿼리 실행이 데이터베이스 내에서 완결되는 효율성을 중시하는 경우 Database 스토리지가 최적입니다. 그 외 모든 경우에는 File Based 스토리지를 사용하십시오.

### 3. 삭제 레코드 처리 방침

대상 시스템에서 레코드를 물리적으로 삭제할지, 논리적 삭제(소프트 딜리트)로 처리할지를 사전에 결정해 두십시오. 감사 목적으로 삭제 레코드를 아카이브하는 것도 검토하십시오.

### 4. Query 모드 주의 사항

* 쿼리 결과 세트에 각 행을 고유하게 식별할 수 있는 열이 포함되어 있는지 확인하십시오.
* 쿼리 끝에 세미콜론(`;`)을 붙이지 마십시오. 시스템이 처리 로직을 추가하기 때문에 세미콜론이 있으면 오류가 발생할 수 있습니다.
* 복수 테이블을 JOIN하는 경우 열 이름의 모호함을 피하기 위해 별칭을 사용하십시오(예: `c.name AS customer_name`).
* `NOW()`나 `RAND()` 같은 비결정성 함수를 쿼리에 포함하지 마십시오. 실행할 때마다 다른 값이 반환되어 모든 행이 "변경됨"으로 판정됩니다.

### 5. 실행 사이에 조건을 변경하지 않기(주의)

WHERE 절이나 쿼리 내용을 실행 사이에 변경하면, 포함되는 행의 집합이 달라지므로 변경 후 첫 실행에서 모든 행이 Upserted(또는 Deleted)로 출력될 가능성이 있습니다. 조건 변경이 필요한 경우, 첫 실행에서는 "전체 차분"이 발생한다는 점을 감안하고 실행하십시오.

## 정리

CDC Database Source는 대규모 데이터셋을 다루는 파이프라인의 효율화에 크게 기여하는 컴포넌트입니다. 스냅샷 비교를 통해 변경 데이터만 추출하고, Upserted records와 Deleted records를 분리하여 출력함으로써 후속 처리를 유연하게 설계할 수 있습니다.

SQL Server라면 Database 스토리지를 통한 고효율 처리가 가능하며, MySQL, PostgreSQL, Snowflake 등 다른 데이터베이스에서도 File Based 스토리지를 통해 동등한 CDC 기능을 활용할 수 있습니다. 또한 Query 모드를 활용하면 복수 테이블의 JOIN 결과에 대해서도 차분 감지가 가능합니다.

먼저 소규모 테스트 데이터셋으로 동작을 검증하고, 변경 감지가 기대한 대로 기능하는지 확인한 후 프로덕션 환경에 적용하십시오.
