Skip to content
Published on

AWS DMS 실전 — 마이그레이션과 지속 복제(CDC)

Authors

들어가며 — 무중단 마이그레이션이라는 숙제

데이터베이스 마이그레이션은 거의 모든 인프라 엔지니어가 한 번쯤 마주치는 통과의례입니다. 온프레미스 오라클을 클라우드로 옮기든, 자체 관리 MySQL을 RDS로 올리든, 비싼 상용 엔진에서 PostgreSQL로 탈출하든, 결국 같은 질문에 부딪힙니다. "서비스를 멈추지 않고, 데이터를 한 건도 잃지 않으면서, 어떻게 옮길 것인가."

가장 단순한 방법은 덤프를 떠서 복원하는 것입니다. 하지만 수백 GB에서 수 TB에 이르는 운영 데이터베이스를 덤프하고 복원하는 동안 서비스를 멈출 수 있는 조직은 많지 않습니다. 덤프를 시작한 순간부터 복원이 끝날 때까지 발생한 변경분을 어떻게 따라잡을 것인가가 핵심 난제입니다.

AWS Database Migration Service, 줄여서 DMS는 바로 이 문제를 정면으로 다룹니다. 초기 데이터를 통째로 옮기는 풀 로드(full load)와, 그 사이 발생한 변경을 실시간으로 따라잡는 변경 데이터 캡처(CDC, Change Data Capture)를 한 도구 안에서 결합해, 소스와 타깃을 거의 실시간으로 동기화된 상태로 유지합니다. 그 상태에서 짧은 컷오버 창만 잡으면 무중단에 가까운 전환이 가능합니다.

이 글에서는 DMS의 구성 요소부터 풀 로드와 CDC의 동작 원리, 이기종 마이그레이션과 SCT 연동, LOB 처리와 데이터 검증, 모니터링과 컷오버 전략, 그리고 네이티브 논리 복제와의 비교까지 실무 관점에서 정리합니다.

DMS란 무엇인가 — 세 개의 구성 요소

DMS를 한 문장으로 정의하면 "소스 데이터베이스에서 타깃 데이터베이스로 데이터를 옮기고 계속 동기화해 주는 관리형 복제 서비스"입니다. 동작을 이해하려면 세 가지 구성 요소를 먼저 알아야 합니다.

  • 복제 인스턴스(Replication Instance): 실제 복제 작업을 수행하는 EC2 기반 관리형 컴퓨트입니다. 소스에서 데이터를 읽어 변환하고 타깃에 쓰는 엔진이 여기서 돕니다.
  • 엔드포인트(Endpoint): 소스와 타깃 데이터베이스에 대한 접속 정보입니다. 엔진 종류, 호스트, 포트, 자격 증명, 추가 연결 속성을 담습니다.
  • 복제 작업(Replication Task): 어떤 테이블을 어떤 방식(풀 로드, CDC, 또는 둘 다)으로 옮길지 정의하는 단위입니다. 테이블 매핑과 작업 설정이 여기에 붙습니다.

이 셋의 관계를 그림으로 그리면 이렇습니다.

+------------------+        +------------------------------+        +------------------+
|  소스 DB          |        |   복제 인스턴스 (관리형 EC2)    |        |  타깃 DB          |
|  (온프레미스/RDS)  |        |                              |        |  (RDS/Aurora 등)  |
|                  |  read  |   +----------------------+   | write  |                  |
|  오라클/MySQL/    | -----> |   |  복제 작업            |   | -----> |  PostgreSQL/      |
|  PostgreSQL/...  |        |   |  - 테이블 매핑        |   |        |  Aurora/...      |
|                  |        |   |  - 풀 로드 + CDC      |   |        |                  |
|  변경 로그        |        |   |  - 변환 규칙          |   |        |                  |
|  (redo/binlog/   |        |   +----------------------+   |        |                  |
|   WAL)           |        |                              |        |                  |
+------------------+        +------------------------------+        +------------------+

복제 인스턴스는 소스와 타깃 사이에 끼어 있는 중계 엔진입니다. 소스의 트랜잭션 로그(오라클의 redo log, MySQL의 binlog, PostgreSQL의 WAL)를 읽어 변경을 캡처하고, 타깃 엔진이 이해하는 형태로 변환해 적용합니다. AWS는 이 인스턴스의 패치, 모니터링, 다중 AZ 장애 조치를 관리해 줍니다.

풀 로드와 CDC — 두 단계의 결합

DMS 작업은 마이그레이션 유형(migration type)에 따라 세 가지 모드로 동작합니다.

  • 풀 로드만(full-load): 현재 시점의 데이터를 통째로 옮기고 끝납니다. 소스가 정지된 상태이거나 일회성 복사면 충분합니다.
  • CDC만(cdc): 특정 시점 이후의 변경만 따라잡습니다. 초기 데이터를 다른 방법으로 이미 옮긴 경우에 씁니다.
  • 풀 로드 + CDC(full-load-and-cdc): 가장 흔한 무중단 마이그레이션 패턴입니다. 초기 데이터를 옮기는 동안 발생한 변경을 기록해 두었다가, 풀 로드가 끝나면 그 변경을 적용해 따라잡고, 이후 실시간 복제로 전환합니다.

풀 로드 + CDC의 전체 흐름을 시간 축으로 그리면 다음과 같습니다.

시간 ───────────────────────────────────────────────────────────────────>

  [풀 로드 시작]                [풀 로드 완료]          [캐시된 변경 적용 완료]
       |                            |                          |
       v                            v                          v
  +---------------------------------+--------------------------+----------------------+
  |        풀 로드 진행 중            |   캐시된 변경 적용         |   지속 복제 (CDC)      |
  |  (테이블 단위 병렬 복사)          |   (그동안 쌓인 변경)       |   (실시간 따라잡기)     |
  +---------------------------------+--------------------------+----------------------+
       |                                                              |
       +-- 이 구간의 소스 변경은 ----------------------------------------+
           내부 캐시 또는 로그로 추적되어 이후 적용됨

핵심은 풀 로드가 진행되는 동안에도 소스의 변경을 놓치지 않는다는 점입니다. DMS는 풀 로드 시작 시점의 로그 위치를 기억하고, 그 이후의 변경을 캐시하거나 로그에서 다시 읽어 풀 로드 완료 후 적용합니다. 이 덕분에 소스를 멈추지 않고도 일관된 상태에 도달할 수 있습니다.

동종과 이기종 — 두 갈래의 마이그레이션

DMS 마이그레이션은 크게 두 갈래로 나뉩니다. 이 구분이 작업의 난이도와 필요한 도구를 결정합니다.

  • 동종(homogeneous) 마이그레이션: 소스와 타깃이 같은 엔진인 경우입니다. 예를 들어 온프레미스 PostgreSQL에서 RDS PostgreSQL로, 또는 자체 MySQL에서 Aurora MySQL로 옮기는 경우입니다. 스키마 구조가 동일하므로 변환이 거의 필요 없습니다.
  • 이기종(heterogeneous) 마이그레이션: 소스와 타깃의 엔진이 다른 경우입니다. 오라클에서 PostgreSQL로, SQL Server에서 Aurora로 옮기는 식입니다. 데이터 타입, 함수, 저장 프로시저, 시퀀스 등 엔진마다 다른 요소를 변환해야 하므로 스키마 변환 도구가 필요합니다.

동종 마이그레이션에서는 DMS만으로 데이터와 변경을 모두 처리할 수 있습니다. 다만 DMS는 기본적으로 테이블과 기본 데이터를 옮기지, 인덱스나 외래 키, 트리거, 시퀀스 같은 보조 객체를 완벽히 옮기지는 않습니다. 그래서 실무에서는 스키마는 네이티브 도구로 먼저 옮기고, 데이터만 DMS로 옮기는 분업이 흔합니다.

이기종 마이그레이션에서는 AWS Schema Conversion Tool(SCT) 또는 DMS Schema Conversion이 등장합니다.

SCT 연동 — 스키마 변환

이기종 마이그레이션의 첫 단계는 스키마 변환입니다. 오라클의 NUMBER 타입을 PostgreSQL의 numeric으로, PL/SQL 프로시저를 PL/pgSQL로, 시퀀스와 트리거를 타깃 문법으로 바꾸는 작업입니다. 이것을 수작업으로 하면 끝이 없으므로, AWS는 Schema Conversion Tool을 제공합니다.

SCT의 작업 흐름은 대략 이렇습니다.

+---------------------+      +------------------------+      +----------------------+
|  소스 스키마          |      |   SCT / DMS 스키마 변환  |      |  타깃 스키마           |
|  (오라클 등)          | ---> |                        | ---> |  (PostgreSQL 등)      |
|                     |      |  - 자동 변환            |      |                      |
|  테이블 / 타입 /      |      |  - 변환 불가 항목 리포트 |      |  변환된 DDL +         |
|  프로시저 / 트리거    |      |  - 변환 난이도 평가      |      |  수동 보정 필요 목록   |
+---------------------+      +------------------------+      +----------------------+

SCT의 진짜 가치는 자동 변환 자체보다 변환 불가 항목을 리포트로 뽑아주는 데 있습니다. 자동으로 변환되는 부분은 손이 안 가지만, 엔진 고유 기능(예: 오라클의 패키지, 자율 트랜잭션, 특정 힌트)은 사람이 다시 설계해야 합니다. SCT는 이런 항목에 변환 난이도를 매겨 마이그레이션 공수를 산정하게 해 줍니다.

스키마 변환이 끝나 타깃에 객체를 만들고 나면, 실제 데이터 이동은 DMS가 담당합니다. 즉 SCT는 "그릇"을 만들고, DMS는 그 그릇에 "내용물"을 채우는 분업입니다.

실전 설정 — 엔드포인트와 작업

이제 실제 설정으로 들어가 봅니다. CLI로 소스 엔드포인트, 타깃 엔드포인트, 복제 작업을 만드는 골격은 다음과 같습니다.

# 1. 소스 엔드포인트 생성 (오라클 예시)
aws dms create-endpoint \
  --endpoint-identifier source-oracle \
  --endpoint-type source \
  --engine-name oracle \
  --server-name oracle.internal.example.com \
  --port 1521 \
  --database-name ORCL \
  --username dms_user \
  --password "REPLACE_WITH_SECRET"

# 2. 타깃 엔드포인트 생성 (PostgreSQL 예시)
aws dms create-endpoint \
  --endpoint-identifier target-postgres \
  --endpoint-type target \
  --engine-name postgres \
  --server-name mydb.cluster-abc.ap-northeast-2.rds.amazonaws.com \
  --port 5432 \
  --database-name appdb \
  --username dms_user \
  --password "REPLACE_WITH_SECRET"

# 3. 연결 테스트
aws dms test-connection \
  --replication-instance-arn arn:aws:dms:ap-northeast-2:111122223333:rep:ABCDEF \
  --endpoint-arn arn:aws:dms:ap-northeast-2:111122223333:endpoint:SOURCE

테이블 매핑은 어떤 스키마와 테이블을 옮길지, 그리고 어떻게 변환할지를 정의하는 JSON입니다. 선택 규칙(selection)과 변환 규칙(transformation)으로 구성됩니다.

{
  "rules": [
    {
      "rule-type": "selection",
      "rule-id": "1",
      "rule-name": "include-app-schema",
      "object-locator": {
        "schema-name": "APP",
        "table-name": "%"
      },
      "rule-action": "include"
    },
    {
      "rule-type": "transformation",
      "rule-id": "2",
      "rule-name": "schema-to-lowercase",
      "rule-target": "schema",
      "object-locator": {
        "schema-name": "APP"
      },
      "rule-action": "convert-lowercase"
    },
    {
      "rule-type": "transformation",
      "rule-id": "3",
      "rule-name": "table-to-lowercase",
      "rule-target": "table",
      "object-locator": {
        "schema-name": "APP",
        "table-name": "%"
      },
      "rule-action": "convert-lowercase"
    }
  ]
}

오라클은 식별자를 대문자로 저장하고 PostgreSQL은 소문자를 선호하므로, 위처럼 스키마와 테이블 이름을 소문자로 변환하는 규칙이 이기종 마이그레이션에서 거의 필수입니다.

작업 설정 — task settings의 핵심

복제 작업의 세부 동작은 task settings JSON으로 제어합니다. 항목이 매우 많지만, 실무에서 손대게 되는 핵심만 추리면 다음과 같습니다.

{
  "TargetMetadata": {
    "SupportLobs": true,
    "FullLobMode": false,
    "LimitedSizeLobMode": true,
    "LobMaxSize": 64,
    "BatchApplyEnabled": true
  },
  "FullLoadSettings": {
    "TargetTablePrepMode": "DROP_AND_CREATE",
    "MaxFullLoadSubTasks": 8,
    "CommitRate": 10000
  },
  "Logging": {
    "EnableLogging": true,
    "LogComponents": [
      { "Id": "SOURCE_CAPTURE", "Severity": "LOGGER_SEVERITY_DEFAULT" },
      { "Id": "TARGET_APPLY", "Severity": "LOGGER_SEVERITY_DEFAULT" }
    ]
  },
  "ValidationSettings": {
    "EnableValidation": true,
    "ThreadCount": 5
  },
  "ErrorBehavior": {
    "DataErrorPolicy": "LOG_ERROR",
    "TableErrorPolicy": "SUSPEND_TABLE"
  }
}

몇 가지 항목을 풀어 설명하면 이렇습니다. TargetTablePrepMode를 DROP_AND_CREATE로 두면 풀 로드 전에 타깃 테이블을 비우고 다시 만듭니다. 이미 스키마를 SCT로 만들어 두었다면 TRUNCATE_BEFORE_LOAD나 DO_NOTHING이 더 안전합니다. MaxFullLoadSubTasks는 동시에 로드할 테이블 수로, 소스와 타깃의 여력에 맞춰 조절합니다. BatchApplyEnabled를 켜면 CDC 변경을 건건이 적용하지 않고 묶어서 적용해 처리량이 크게 올라갑니다.

LOB 처리 — 큰 객체의 함정

DMS에서 가장 많이 발목을 잡는 주제가 LOB(Large Object), 즉 BLOB과 CLOB 같은 대형 객체 처리입니다. DMS가 LOB을 다루는 방식은 세 가지입니다.

모드동작장점단점
Full LOB Mode크기 제한 없이 모든 LOB을 옮김데이터 손실 없음느림, 메모리 부담 큼
Limited LOB Mode지정한 최대 크기까지만 옮김빠름, 예측 가능한도 초과분은 잘림
Inline LOB Mode작은 LOB은 인라인, 큰 것만 별도 처리균형이 좋음설정이 다소 복잡

실무에서 가장 흔한 선택은 Limited LOB Mode입니다. LobMaxSize를 충분히 크게 잡되, 그 한도를 넘는 LOB이 잘릴 수 있다는 점을 반드시 인지해야 합니다. 한도를 너무 작게 잡으면 데이터가 조용히 잘려 나가고, 너무 크게 잡으면 성능이 급락합니다.

LOB이 있는 테이블에는 또 한 가지 제약이 있습니다. DMS가 LOB을 옮기려면 해당 테이블에 기본 키 또는 고유 키가 있어야 한다는 점입니다. 키가 없으면 LOB 컬럼은 NULL로 적재되거나 테이블이 통째로 건너뛰어집니다. 그래서 마이그레이션 전에 LOB 테이블의 키 존재 여부를 점검하는 것이 중요합니다.

LOB 처리 의사결정 흐름

  LOB 컬럼이 있는가?
        |
   아니오 ----> Limited/Full 설정 무관, 빠르게 진행
        |
        |
   기본 키가 있는가?
        |
   아니오 ----> 먼저 키를 추가하거나 별도 처리 (그대로 두면 누락 위험)
        |
        |
   LOB 최대 크기를 아는가?
        |
   예 ----> Limited LOB Mode + LobMaxSize 여유 있게
        |
   아니오 ----> Full LOB Mode (느리지만 안전) 또는 Inline 검토

데이터 검증 — 옮긴 뒤가 진짜 시작

데이터를 옮겼다고 끝이 아닙니다. 소스와 타깃의 데이터가 정말로 일치하는지 검증해야 합니다. DMS는 task settings에서 검증을 켜면 행 단위로 소스와 타깃을 비교하는 데이터 검증 기능을 제공합니다.

검증은 풀 로드와 CDC가 끝난 행을 대상으로, 컬럼 값을 해시하거나 직접 비교해 불일치를 찾아냅니다. 결과는 작업 통계와 검증 전용 테이블에서 확인할 수 있습니다.

# 작업의 테이블별 통계와 검증 상태 확인
aws dms describe-table-statistics \
  --replication-task-arn arn:aws:dms:ap-northeast-2:111122223333:task:MYTASK \
  --query "TableStatistics[].{Table:TableName,State:TableState,Validation:ValidationState,Failed:ValidationFailedRecords}"

검증 상태가 "Validated"이면 일치, "Mismatched records"가 잡히면 불일치입니다. 불일치가 나오는 흔한 원인은 타임존 처리, 부동소수점 정밀도 차이, 문자 인코딩, 그리고 앞서 말한 LOB 잘림입니다. 검증을 켜면 복제 부하가 늘어나므로, 운영 영향이 큰 경우에는 검증 스레드 수를 조절하거나 별도 검증 작업으로 분리하기도 합니다.

검증은 "옮겼다"와 "제대로 옮겼다" 사이의 간극을 메우는 안전장치입니다. 마이그레이션에서 가장 무서운 것은 실패가 아니라 조용한 데이터 손상이므로, 검증을 생략하는 선택은 권하지 않습니다.

모니터링과 재시작 — 운영의 실제

DMS 작업은 띄워 놓고 잊는 것이 아니라 꾸준히 지켜봐야 합니다. 핵심 지표는 CloudWatch로 노출됩니다.

지표의미주목해야 할 때
CDCLatencySource소스에서 변경을 읽어오는 지연값이 커지면 소스 로그 읽기 병목
CDCLatencyTarget타깃에 변경을 적용하는 지연값이 커지면 타깃 쓰기 병목
FullLoadThroughputRowsTarget풀 로드 초당 행 수풀 로드 속도 점검
FreeableMemory복제 인스턴스 가용 메모리부족하면 인스턴스 증설 필요
CDCIncomingChanges대기 중인 변경 수계속 쌓이면 적용이 못 따라감

두 가지 지연 지표를 나눠서 보는 것이 중요합니다. 소스 지연이 크면 소스 트랜잭션 로그를 읽는 단계가 느린 것이고, 타깃 지연이 크면 타깃에 적용하는 단계가 느린 것입니다. 원인이 다르니 처방도 다릅니다. 타깃 지연은 BatchApplyEnabled를 켜거나 타깃 인덱스를 마이그레이션 중 잠시 비활성화해 완화할 수 있습니다.

작업이 멈췄을 때의 재시작 전략도 미리 정해 둬야 합니다. DMS 작업은 처음부터 다시 시작(restart)하거나 중단된 지점부터 이어서 시작(resume)할 수 있습니다.

# 중단 지점부터 이어서 재개 (CDC 위치 유지)
aws dms start-replication-task \
  --replication-task-arn arn:aws:dms:ap-northeast-2:111122223333:task:MYTASK \
  --start-replication-task-type resume-processing

# 특정 시점부터 CDC 시작 (체크포인트 기반)
aws dms start-replication-task \
  --replication-task-arn arn:aws:dms:ap-northeast-2:111122223333:task:MYTASK \
  --start-replication-task-type start-replication \
  --cdc-start-position "checkpoint:V1#34#..."

resume은 마지막 체크포인트부터 이어가므로 데이터를 다시 옮기지 않습니다. 반면 풀 로드를 처음부터 다시 돌리면 그동안 쌓인 타깃 변경이 덮어써질 수 있으니, 재시작 유형의 의미를 정확히 알고 선택해야 합니다.

컷오버 전략 — 전환의 순간

마이그레이션의 클라이맥스는 컷오버, 즉 애플리케이션을 소스에서 타깃으로 전환하는 순간입니다. 풀 로드 + CDC로 두 데이터베이스가 거의 실시간으로 동기화된 상태라면, 컷오버는 짧은 창 안에 끝낼 수 있습니다.

권장하는 컷오버 절차는 다음과 같습니다.

컷오버 절차

1. CDC 지연이 거의 0인지 확인 (CDCLatencyTarget 모니터링)
2. 소스로 들어오는 쓰기를 잠시 차단 (읽기 전용 모드 또는 트래픽 중단)
3. 남은 변경이 모두 타깃에 적용될 때까지 대기 (대기 변경 0 확인)
4. 데이터 검증 최종 확인 (행 수, 검증 상태)
5. 시퀀스/자동증가 값 보정 (DMS는 시퀀스 현재값을 옮기지 않음)
6. 애플리케이션 연결 문자열을 타깃으로 전환
7. 타깃에서 정상 동작 확인 후 트래픽 개방
8. 문제 시 소스로 롤백할 수 있도록 일정 기간 소스 보존

여기서 자주 빠뜨리는 5번 단계를 강조하고 싶습니다. DMS는 테이블의 행 데이터를 옮기지만, 시퀀스나 자동 증가 컬럼의 "다음 값" 상태는 옮기지 않습니다. 이를 보정하지 않고 컷오버하면 타깃에서 새 행을 넣을 때 기본 키 충돌이 발생합니다. 컷오버 직전에 각 시퀀스의 현재 최대값을 조회해 타깃 시퀀스를 그 위로 재설정하는 작업이 필수입니다.

또한 8번처럼 롤백 경로를 열어 두는 것이 중요합니다. 컷오버 후 예상치 못한 문제가 생기면 빠르게 소스로 되돌릴 수 있어야 하므로, 소스를 즉시 폐기하지 말고 일정 기간 유지합니다. 더 보수적인 팀은 타깃에서 소스로 거꾸로 복제하는 역방향 CDC를 미리 구성해 두기도 합니다.

한계와 비용 — 알고 써야 할 것들

DMS는 강력하지만 만능은 아닙니다. 알고 들어가야 할 한계가 있습니다.

첫째, DMS는 데이터를 옮기지 전체 스키마를 옮기지 않습니다. 기본 테이블과 기본 키 정도는 만들어 주지만, 보조 인덱스, 외래 키, 트리거, 저장 프로시저, 뷰, 시퀀스 등은 기본적으로 옮기지 않습니다. 이들은 SCT나 네이티브 도구로 별도로 처리해야 합니다.

둘째, 풀 로드 중에는 외래 키와 트리거가 방해가 됩니다. 그래서 보통 풀 로드 동안 타깃의 외래 키와 트리거를 비활성화하고, 풀 로드가 끝난 뒤 다시 켭니다. 그렇지 않으면 테이블 적재 순서 때문에 제약 위반이 발생합니다.

셋째, CDC는 소스의 트랜잭션 로그에 의존합니다. 소스에서 보조 로깅(오라클의 supplemental logging, MySQL의 binlog ROW 포맷, PostgreSQL의 logical replication 설정)을 켜 두지 않으면 CDC가 동작하지 않습니다. 이 사전 설정을 빠뜨리면 풀 로드는 되는데 CDC가 안 되는 당황스러운 상황을 만납니다.

비용은 크게 두 축입니다. 복제 인스턴스의 시간당 요금과 데이터 전송 요금입니다. 복제 인스턴스는 인스턴스 클래스와 가동 시간에 비례하므로, 마이그레이션이 끝나면 잊지 말고 작업과 인스턴스를 정리해야 합니다. 같은 리전 안에서의 전송은 저렴하지만, 리전 간이나 인터넷 경유 전송은 비용이 붙습니다. 비용을 대략적으로 표현하면 다음과 같습니다.

DMS 비용의 주요 구성

  복제 인스턴스 요금  =  인스턴스 클래스 단가  x  가동 시간
  스토리지 요금       =  로그/캐시용 할당 스토리지 x  GB-월
  데이터 전송 요금    =  리전 간/인터넷 구간 전송량 x  GB 단가
  (같은 AZ/리전 내부 전송은 일반적으로 무료 또는 저렴)

가장 흔한 비용 낭비는 마이그레이션이 끝났는데도 복제 인스턴스를 끄지 않고 방치하는 것입니다. CDC를 영구 복제 용도로 계속 쓸 것이 아니라면, 컷오버 검증이 끝나는 즉시 자원을 정리하는 절차를 체크리스트에 넣어 두는 것이 좋습니다.

대안 비교 — 네이티브 논리 복제

DMS가 유일한 답은 아닙니다. 동종 마이그레이션, 특히 PostgreSQL 사이의 이동에서는 엔진이 기본 제공하는 논리 복제(logical replication)가 더 단순하고 빠른 경우가 많습니다. 두 접근을 비교하면 이렇습니다.

기준AWS DMS네이티브 논리 복제
이기종 지원강점 (엔진 간 변환)거의 불가 (같은 엔진 위주)
동종 성능양호대체로 더 빠르고 충실
스키마 변환SCT와 연동직접 처리
운영 부담관리형, 콘솔 통합직접 구성과 모니터링
데이터 검증내장 검증 기능별도 도구 필요
변환 규칙풍부한 매핑 규칙제한적
비용인스턴스 요금 발생엔진 자체 기능, 추가 비용 적음
적합한 상황이기종, 복잡한 변환동종, 단순 복제

거칠게 요약하면 이렇습니다. 오라클이나 SQL Server에서 PostgreSQL로 가는 이기종 마이그레이션이라면 DMS와 SCT의 조합이 사실상 표준입니다. 반면 PostgreSQL에서 PostgreSQL로, MySQL에서 MySQL로 가는 동종 마이그레이션이라면 엔진 네이티브 논리 복제가 더 충실하고 비용도 낮은 경우가 많습니다. PostgreSQL의 publication과 subscription, MySQL의 복제는 시퀀스와 제약을 포함해 더 완전하게 따라가는 경향이 있습니다.

실무에서는 둘을 섞기도 합니다. 예를 들어 스키마와 보조 객체는 네이티브 덤프로 옮기고, 대용량 데이터의 무중단 이동만 DMS로 처리하는 식입니다. 도구는 목적에 맞춰 조합하는 것이지, 하나로 모든 것을 해결하려 할 필요는 없습니다.

자주 밟는 함정

마지막으로 현장에서 반복적으로 마주치는 함정들을 모았습니다.

첫째, 보조 로깅을 빠뜨립니다. CDC가 동작하려면 소스에서 적절한 로깅을 켜야 하는데, 이를 마이그레이션 당일에 발견하면 일정이 틀어집니다. 오라클은 supplemental logging, MySQL은 binlog ROW 포맷, PostgreSQL은 wal_level을 logical로 설정해야 합니다.

둘째, 기본 키 없는 테이블을 간과합니다. 기본 키가 없으면 CDC의 UPDATE와 DELETE가 제대로 동작하지 않고, LOB도 누락될 수 있습니다. 마이그레이션 전에 키 없는 테이블을 목록화해 대응책을 정해야 합니다.

셋째, LOB 한도를 잘못 잡습니다. Limited LOB Mode에서 LobMaxSize를 너무 작게 잡으면 데이터가 조용히 잘립니다. 소스의 실제 LOB 최대 크기를 미리 조사해야 합니다.

넷째, 외래 키와 트리거를 끄지 않습니다. 풀 로드 중 타깃의 제약과 트리거가 살아 있으면 적재 순서 문제로 실패하거나 의도치 않은 부작용이 생깁니다.

다섯째, 시퀀스 보정을 잊습니다. 컷오버 후 기본 키 충돌의 단골 원인입니다.

여섯째, 자원을 정리하지 않습니다. 끝난 작업과 복제 인스턴스를 방치해 비용이 새는 경우가 많습니다.

실전 체크리스트

마이그레이션을 단계별로 점검할 수 있도록 체크리스트로 정리했습니다.

[ 사전 준비 ]
[ ] 소스/타깃 엔진 버전과 DMS 지원 여부 확인
[ ] 소스에 보조 로깅 활성화 (supplemental/binlog/wal_level)
[ ] 기본 키 없는 테이블 목록화 및 대응책 결정
[ ] LOB 컬럼의 실제 최대 크기 조사
[ ] DMS 전용 계정과 최소 권한 부여
[ ] 네트워크 경로와 보안 그룹/방화벽 확인

[ 스키마 준비 ]
[ ] (이기종) SCT로 스키마 변환 및 변환 불가 항목 처리
[ ] 타깃에 테이블/타입 생성
[ ] 풀 로드용으로 외래 키/트리거 비활성화 계획 수립

[ 작업 구성 ]
[ ] 복제 인스턴스 크기와 다중 AZ 결정
[ ] 테이블 매핑(선택/변환 규칙) 작성
[ ] task settings에서 LOB 모드와 검증 설정
[ ] 로깅과 CloudWatch 알람 구성

[ 실행과 검증 ]
[ ] 연결 테스트 통과 확인
[ ] 풀 로드 진행률과 처리량 모니터링
[ ] CDC 지연(소스/타깃) 모니터링
[ ] 데이터 검증 상태 확인 및 불일치 조사

[ 컷오버 ]
[ ] CDC 지연 0 근접 확인
[ ] 소스 쓰기 차단 및 잔여 변경 적용 대기
[ ] 시퀀스/자동증가 값 보정
[ ] 외래 키/트리거 재활성화
[ ] 연결 문자열 전환 및 정상 동작 확인
[ ] 롤백 경로 유지 (소스 보존)

[ 마무리 ]
[ ] 복제 작업 중지 및 삭제
[ ] 복제 인스턴스 삭제
[ ] 사후 모니터링과 성능 확인

마치며

DMS의 가치는 화려한 기술이 아니라 정확한 문제 정의에 있습니다. 무중단 마이그레이션의 본질은 "초기 데이터를 옮기는 동안 발생한 변경을 어떻게 따라잡을 것인가"이고, DMS는 풀 로드와 CDC를 한 도구로 묶어 이 문제를 깔끔하게 해결합니다. 여기에 이기종 변환을 위한 SCT, 무결성을 위한 데이터 검증, 운영을 위한 모니터링과 재시작이 더해져 마이그레이션의 전 과정을 받쳐 줍니다.

다만 DMS는 마법이 아닙니다. 보조 로깅, 기본 키, LOB 한도, 시퀀스 보정 같은 디테일을 챙기지 않으면 조용한 데이터 손상이라는 가장 무서운 결과를 만납니다. 그리고 동종 마이그레이션이라면 네이티브 논리 복제가 더 나은 선택일 수 있다는 점도 기억해 둘 만합니다. 도구의 강점과 한계를 정확히 알고, 체크리스트로 디테일을 챙기는 것. 결국 안전한 마이그레이션은 그 성실함의 결과입니다.

참고 자료