고급5분 분량

DynamoDB Streams 완전 가이드 (예제 포함)

DynamoDB Streams는 변경 데이터 캡처 로그입니다: 테이블의 모든 삽입, 업데이트, 삭제가 순서대로, 여러분이 반응할 수 있는 레코드 스트림으로 캡처됩니다. 폴링 없이 테이블을 이벤트 소스로 바꾸는 방법입니다.

감사 로그 시나리오에서 여러분은 민감한 이벤트가 안착하는 순간 반응하고 싶습니다 — 누군가 청구서를 내보내거나 관리자 역할을 부여할 때 알림을 발생시키는 것 — 타이머로 테이블을 스캔하지 않고서 말입니다. Streams는 그것의 푸시 쪽입니다.

DynamoDB Streams는 어떻게 작동하나요?

DynamoDB Streams는 테이블의 모든 삽입, 업데이트, 삭제를, 최대 24시간 동안 보관되는, 시간 순서로 정렬되고 중복 제거된 레코드 로그로 캡처합니다. StreamViewType으로 각 레코드가 무엇을 담을지(키, 새 이미지, 이전 이미지, 또는 둘 다) 선택한 뒤, Lambda 트리거로 스트림을 소비해 폴링 없이 항목 변경에 반응합니다.

  • Streams는 항목 수준 변경을 캡처합니다, 시간 순서로 정렬되고 중복 제거된 로그로서, 최대 24시간 보관됩니다.
  • 각 레코드가 무엇을 담을지 선택합니다 StreamViewType으로: 키만, 새 이미지, 이전 이미지, 또는 이전과 새 이미지 둘 다.
  • 레코드는 항목별로 순서가 보장됩니다 — 한 항목에 대한 변경은 쓰인 순서대로 도착합니다 — 그리고 스트림은 과 같은 방식으로 샤딩됩니다.
  • 네이티브 소비자는 Lambda입니다 — 새 레코드 배치마다 실행되는 트리거이며, 더 풍부한 팬아웃을 위한 대안으로 Kinesis Data Streams가 있습니다.

문제: 폴링 없이 반응하기

여러분은 "role.granted 이벤트가 쓰이면 알려줘"가 필요합니다. 순진한 접근은 매 분 새 이벤트를 스캔하는 예약 작업입니다 — 매번 최근 파티션 전체를 읽고, 용량을 쓰고, 항상 최소 1분은 늦습니다.

여러분이 실제로 원하는 것은 푸시입니다: 항목이 변경되는 순간 DynamoDB가 알려주는 것. 그것이 정확히 Streams가 제공하는 것이며, 변경 레코드가 여러분이 찾아 나서는 대신 여러분의 코드로 배달됩니다.

Streams는 어떻게 작동하는가

AWS 문서에 따르면, DynamoDB Streams는 네이티브 Lambda 통합과 함께 최대 24시간 동안 중복 제거되고 시간 순서로 정렬된 변경 로그를 유지합니다 (DynamoDB의 변경 데이터 캡처). 각 레코드는 하나의 항목 수준 수정을 기술합니다.

스트림을 활성화할 때 StreamViewType을 고르며, 이것은 각 레코드가 변경된 항목의 얼마만큼을 담는지 제어합니다:

StreamViewTypeeach record contains
KEYS_ONLYonly the key attributes of the changed item
NEW_IMAGEthe entire item as it looks after the change
OLD_IMAGEthe entire item as it looked before the change
NEW_AND_OLD_IMAGESboth the before and after images

레코드는 항목별로 순서가 보장됩니다 — 단일 항목에 대한 변경은 쓰인 순서대로 나타납니다 — 그리고 스트림은 테이블과 같은 파티션 구조를 따라 샤딩됩니다. 보관은 24시간입니다 — Streams는 영구 이력이 아니라 반응 버퍼입니다. 내구성 있는 이력을 위해서는 이벤트 자체를 저장하세요 (그것이 정확히 우리 감사 로그 테이블이 이미 하는 일입니다).

네이티브 소비자는 Lambda 트리거입니다: DynamoDB는 새 스트림 레코드가 도착하는 대로 그 배치로 여러분의 함수를 호출합니다.

LambdaStream"DynamoDB"AppLambdaStream"DynamoDB"App"EVENT role.granted 쓰기""변경 레코드 (NEW_IMAGE)""레코드 배치""민감한 작업이면 → 알림"

실제 예제: 민감한 감사 이벤트에 알림 발생

감사 로그 테이블은 NEW_IMAGE를 가진 스트림을 얻으므로, 각 레코드는 전체 새 이벤트를 담습니다. Lambda가 그 배치를 소비하고 중요한 레코드만 전달합니다:

stream record (NEW_IMAGE)consumer action
TENANT#acmeEVENT#…#a2action=invoice.exportsend to SIEM
TENANT#globex EVENT#…#b9 action=role.grantedpage on-call
TENANT#acmeEVENT#…#a1action=login.successignore

함수는 테이블을 결코 건드리지 않습니다 — 순전히 스트림이 건네는 것에 반응합니다. 폴링도, 스캔도 없고, 알림은 쓰기 후 몇 초 안에 발생합니다. 스트림 레코드는 항목별로 순서가 보장되므로, 같은 이벤트 항목에 대한 연속된 변경은 쓰인 순서대로 도착합니다.

이것은 또한 다운스트림 복사본을 유지하는 표준 방법입니다: 스트림 소비자는 각 이벤트를 전문 감사 검색을 위해 OpenSearch로 프로젝션하거나, 개수를 집계할 수 있습니다 — 모두 같은 변경 로그에서 파생됩니다.

DynoTable에서 해보기

스트림 소비자를 연결하기 전에, 여러분의 Lambda가 받을 항목의 정확한 형태를 알아야 합니다 — 어떤 속성이 존재하는지, 중첩된 맵과 리스트가 어떻게 보이는지, NEW_IMAGE 레코드가 실제로 무엇을 담을지 말입니다.

샘플 항목을 일반 JSON과 스트림 레코드가 쓰는 속성-값 형태 사이에서 변환하려면, DynamoDB JSON 변환기가 여러분의 브라우저에서 그것을 합니다. 그리고 DynoTable에서는 전체 항목을 — DynamoDB-JSON 형태를 포함해 — 살펴볼 수 있으므로, 필드 형태를 추측하는 대신 실제 데이터에 대해 NEW_IMAGE 레코드를 모델링할 수 있습니다.

DynoTable에서 감사 이벤트 항목을 살펴보며 Lambda 소비자가 받을 NEW_IMAGE 스트림 레코드를 모델링하기.
DynoTable에서 감사 이벤트 항목을 살펴보며 Lambda 소비자가 받을 NEW_IMAGE 스트림 레코드를 모델링하기.

소비자를 로컬에서 테스트한다면, 테이블을 DynamoDB Local에 대해 실행하고 같은 방식으로 살펴보세요 — DynamoDB Local에 연결하기를 참고하세요.

함정과 다음 단계

  • 24시간은 백로그가 아닙니다. 소비자가 하루 동안 다운되면, 레코드는 만료되어 사라집니다. Streams는 내구성 있는 재생이 아니라 준실시간 반응을 위한 것입니다 — 이력을 위해서는 이벤트 자체를 보관하세요.
  • 필요한 가장 작은 StreamViewType을 고르세요. NEW_AND_OLD_IMAGES는 페이로드를 두 배로 만듭니다. 항목을 다시 읽으러 갈 키만 필요하다면, KEYS_ONLY가 더 저렴합니다.
  • 순서는 항목별이지, 파티션 키별이나 전역이 아닙니다. DynamoDB는 같은 항목에 대한 연속된 변경에 대해서만 순서를 보장합니다. 서로 다른 항목 간에는, 한 파티션 키 안에서조차 순서 보장이 없습니다.
  • TTL 삭제는 스트림 레코드로 나타납니다 시스템 속성 마커와 함께, 이것이 여러분이 만료되는 항목을 아카이빙하는 방법입니다 — DynamoDB TTL을 참고하세요.

Streams는 감사 로그를 이벤트 소스로 바꿉니다. 다음 운영 관심사는 항목 생애의 반대쪽 끝입니다 — DynamoDB TTL로 오래된 이벤트를 자동으로 만료시키는 것.

DynoTable을 다운로드해 Lambda 코드 한 줄을 쓰기 전에 여러분의 스트림 소비자가 받을 정확한 항목 형태를 살펴보세요.

업데이트됨