누락된 연결 고리: 레거시 데이터베이스에서 AWS DMS로 Serverless 이벤트 트리거

발행: (2026년 1월 8일 오전 04:09 GMT+9)
9 min read
원문: Dev.to

Source: Dev.to

by khaldoun488

우리는 모든 것이 이벤트‑드리븐이 되길 원하는 세상에 살고 있습니다. SQL 데이터베이스에 새로운 사용자가 등록되면 즉시:

  • SES를 통해 환영 이메일을 발송하고,
  • API를 통해 CRM을 업데이트하고,
  • Step Functions 워크플로우를 시작해야 합니다.

DynamoDB를 사용해 새로 구축한다면(​DynamoDB Streams​) 이는 쉽습니다. 하지만 데이터가 레거시 MySQL 모놀리식, 온‑프레미스 Oracle DB, 혹은 일반 PostgreSQL 인스턴스에 있다면 어떨까요?

**Change Data Capture (CDC)**가 필요합니다—변경 사항을 클라우드로 스트리밍해야 합니다.

당연히 **AWS DMS (Database Migration Service)**를 살펴보게 됩니다. 데이터 이동에는 완벽하지만, 곧 벽에 부딪히게 됩니다:

문제

AWS DMS는 AWS Lambda 함수를 직접 대상으로 지정할 수 없습니다.
단순히 “테이블 X에 행이 삽입될 때 함수 Y를 호출한다”는 작업을 구성할 수 없습니다.

그렇다면 “구시대”(SQL)와 “신시대”(서버리스) 사이의 격차를 어떻게 메울 수 있을까요? 많은 사람들이 Kinesis를 제안하지만, 가장 견고하고 비용 효율적인 답은 Amazon S3입니다.

아래는 레거시 백‑엔드를 재작성 없이 현대화하기 위해 제가 사용하는 아키텍처 패턴입니다.

아키텍처: “S3 Drop” 패턴

  1. Source – DMS가 레거시 데이터베이스에 연결하여 트랜잭션 로그를 통해 변경 사항(INSERT/UPDATE/DELETE)을 캡처합니다.
  2. Target – DMS가 해당 변경 사항을 JSON 파일로 S3 버킷에 기록합니다.
  3. Trigger – S3가 새로운 파일을 감지하고 이벤트 알림을 발생시킵니다.
  4. ComputeLambda 함수가 이벤트를 수신하고 파일을 읽어 비즈니스 로직을 처리합니다.

Architecture diagram

왜 Kinesis 또는 Airbyte 대신 S3를 사용하나요?

왜 Kinesis Data Streams를 사용하지 않나요?

  • 비용 – 레거시 DB가 조용할 때, 프로비저닝된 Kinesis 스트림보다 S3가 훨씬 저렴합니다.
  • 가시성 – 버킷에 파일로 변경 사항을 직접 확인할 수 있어 디버깅이 10배 쉬워집니다.
  • 배치 처리 – DMS가 S3에 배치로 기록하므로, 대규모 쓰기 급증 시 Lambda 호출이 자연스럽게 제한됩니다.

왜 Airbyte 또는 Fivetran을 사용하지 않나요?

  • 해당 도구들은 ELT 파이프라인(예: 15–60 분마다 Snowflake에 데이터 로드)에 강점이 있습니다.
  • 우리의 목표는 이벤트‑드리븐 처리—가능한 한 “실시간”에 가깝게 Lambda를 트리거하는 것입니다.
  • AWS DMS는 연속 CDC를 제공하여 배치 기반 ELT 도구가 놓치기 쉬운 세밀한 이벤트 스트림을 전달합니다.
  • 100 % AWS‑네이티브 환경을 유지하면 엄격한 기업 환경에서 IAM 거버넌스를 단순화할 수 있습니다.

Implementation Guide

DMS Endpoint Settings

DMS에서 대상 엔드포인트(S3)를 만들 때 기본값에 의존하지 마세요. 출력이 Lambda에 친화적이도록 다음 Extra Connection Attributes를 사용합니다:

dataFormat=json;
datePartitionEnabled=true;
  • dataFormat=json – DMS는 기본적으로 CSV를 사용합니다; JSON이 Lambda에서 파싱하기 훨씬 쉽습니다.
  • datePartitionEnabled=true – 파일을 날짜별로 정리합니다(/2023/11/02/...). 이렇게 하면 하나의 폴더에 수백만 개의 객체가 쌓이는 것을 방지할 수 있습니다.

Understanding the Event Structure

전형적인 DMS‑생성 파일은 다음과 같습니다(라인 구분 JSON, NDJSON라고도 함):

{
    "data": { "id": 101, "username": "jdoe", "status": "active" },
    "metadata": { "operation": "insert", "timestamp": "2023-11-02T10:00:00Z" }
}
{
    "data": { "id": 102, "username": "asmith", "status": "pending" },
    "metadata": { "operation": "update", "timestamp": "2023-11-02T10:05:00Z" }
}

각 라인에는 operation(insert, update, delete)과 payload(data)가 깔끔하게 포함됩니다.

Lambda Logic

DMS가 NDJSON을 기록하기 때문에 파일 전체에 json.loads()를 한 번에 호출할 수 없습니다. 라인 단위로 반복해야 합니다.

아래는 파일을 올바르게 처리하는 Python 보일러플레이트입니다:

import boto3
import json

s3 = boto3.client('s3')

def handler(event, context):
    # 1️⃣ S3 이벤트에서 버킷과 키 추출
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key    = record['s3']['object']['key']

        print(f"Processing file: s3://{bucket}/{key}")

        # 2️⃣ DMS가 생성한 파일 가져오기
        obj = s3.get_object(Bucket=bucket, Key=key)
        content = obj['Body'].read().decode('utf-8')

        # 3️⃣ NDJSON 파싱 (라인 구분 JSON)
        for line in content.splitlines():
            if not line.strip():
                continue  # 빈 라인 건너뛰기

            row = json.loads(line)

            # 4️⃣ operation 타입에 따라 필터링 / 처리
            operation = row.get('metadata', {}).get('operation')
            if operation == 'insert':
                user_data = row.get('data')
                # TODO: insert에 대한 비즈니스 로직 추가
                print(f"INSERT: {user_data}")

            elif operation == 'update':
                user_data = row.get('data')
                # TODO: update에 대한 비즈니스 로직 추가
                print(f"UPDATE: {user_data}")

            elif operation == 'delete':
                # 필요 시 delete 처리
                print("DELETE operation received")

핵심 포인트

  • 전체 파일에 json.loads(content)사용하지 말 것.
  • content.splitlines()로 라인별로 반복하면서 각각을 파싱할 것.
  • 로직 라우팅을 위해 metadata.operation 필드를 활용할 것.

TL;DR

  • Capture CDC를 기존 레거시 RDBMS에서 AWS DMS로 캡처합니다.
  • 변경 사항을 JSON 파일로 S3에 (날짜별 파티션) 저장합니다.
  • S3 이벤트 알림을 통해 LambdaTrigger합니다.
  • NDJSON 페이로드를 한 줄씩 Parse하고 이벤트 기반 비즈니스 로직을 구현합니다.

이 “S3 Drop” 패턴은 구식 데이터베이스와 최신 서버리스 워크플로우 사이에 저비용, 가시성 확보, 완전한 AWS‑네이티브 브리지를 제공합니다. 🚀

print(f"New User Detected: {user_data['username']}")
# trigger_welcome_email(user_data)

elif operation == 'update':
    print(f"User Updated: {row['data']['id']}")

Summary

서버리스의 이점을 얻기 위해 전체 레거시 데이터베이스를 리팩터링할 필요는 없습니다. AWS DMS를 사용해 데이터를 추출하고 S3를 신뢰할 수 있는 버퍼로 활용하면, 20‑년 된 데이터베이스에서도 최소한의 마찰로 최신 Lambda 워크플로를 트리거할 수 있습니다. 이 패턴은 순수한 속도보다 안정성과 가시성을 우선시하며 – 기업 마이그레이션에서 보통 가치가 있는 트레이드‑오프입니다.

Back to Blog

관련 글

더 보기 »

Omarchy는 괜찮은가...?

개요: 만약 당신이 바위 밑에 살아왔다면, 아마도 Omarchy Linux에 대한 소문을 들어봤을 것입니다 – 37signals 공동 설립자 David...