Amazon Web Services 한국 블로그

Amazon DynamoDB 트랜잭션 기능 출시 (서울 리전 포함) 및 활용 방법

오랫동안 고객은 마이크로서비스 및 모바일 백엔드 구축에서 게임 및 IoT 솔루션 구현에 이르기까지 다양한 사용 사례에서 Amazon DynamoDB를 사용해 왔습니다. 예를 들어, Capital One은 메인프레임 트랜잭션을 서버리스 아키텍처로 이전하여 모바일 애플리케이션의 대기 시간을 줄이는 데 DynamoDB를 사용합니다. Tinder는 가동을 중단하지 않고도 사용자 데이터를 DynamoDB로 마이그레이션하여 글로벌 사용자 기반을 지원하는 데 필요한 확장성을 확보하였습니다.

개발자들은 때론 하나 이상의 테이블에서 여러 개의 별도 작업을 묶는 비즈니스 로직을 구현해야 합니다. 이 같은 요구 사항 때문에 구현에 불필요한 복잡성이 더해질 수 있습니다. 이제 Dynamo DB에 네이티브 트랜잭션 지원을 통해 이러한 사용 사례를 보다 쉽게 구축할 수 있습니다!

Amazon DynamoDB 트랜잭션(Transactions) 소개

Amazon DynamoDB 트랜잭션은 개발자에게 단일 AWS 계정 및 리전에 있는 하나 이상의 테이블에서 ACID(원자성, 일관성, 격리, 영속성)를 제공합니다. 하나의 비지니스 로직 작업 중에 여러 항목에 대해 삽입, 삭제 또는 업데이트를 조정해야 하는 애플리케이션을 구축할 때 트랜잭션을 사용할 수 있습니다. DynamoDB는 여러 파티션과 테이블에서 트랜잭션을 지원하는 최초의 비관계형 데이터베이스가 되었습니다.

트랜잭션은 DynamoDB의 확장성과 성능, 엔터프라이즈급 혜택을 보다 다양한 워크로드로 확장시킵니다. 트랜잭션을 사용하면 많은 사용 사례를 보다 쉽고 빠르게 구현할 수 있습니다. 예를 들어, 다음과 같습니다.

  • 금융 트랜잭션 처리
  • 주문 이행 및 관리
  • 멀티플레이어 게임 엔진 구축
  • 분산된 구성 요소 및 서비스에서 작업 조정

트랜잭션 처리를 위해 다음과 같은 두 개의 새로운 DynamoDB 작업이 도입되었습니다.

  • TransactWriteItems. 하나 이상의 PutItem, UpdateItem 및 DeleteItem 작업에서 쓰기 세트를 포함하는 배치 작업입니다. TransactWriteItems는 선택적으로 업데이트하기 전에 충족해야 하는 전제 조건을 확인할 수 있습니다. 이러한 조건으로는, 쓰기 세트의 조건과 같거나 다른 항목이 포함될 수 있습니다. 조건을 충족하지 못하면 트랜잭션이 거부됩니다.
  • TransactGetItems. 하나 이상의 GetItem 작업에서 읽기 세트를 포함하는 배치 작업입니다. 활성 쓰기 트랜잭션에 포함된 항목에서 TransactGetItems 요청이 실행되면 읽기 트랜잭션이 취소됩니다. 이전에 커미트한 값을 가져오려면 표준 읽기를 사용할 수 있습니다.

각 트랜잭션은 조건을 포함하여 최대 10개의 고유한 항목 또는 최대 4MB의 데이터를 포함할 수 있습니다.

이 새로운 기능을 통해 DynamoDB는 서로 다른 애플리케이션 요구 사항을 충족하기 위해 여러 읽기 및 쓰기 옵션을 제공하며, 이를 통해 개발자에게 복잡한 데이터 중심 비즈니스 논리를 구현할 때 뛰어난 유연성을 제공합니다.

  • 읽기에 대한 세 가지 옵션 – 최종 일관성, 강력한 일관성, 트랜잭션 기능.
  • 쓰기에 대한 두 가지 옵션 – 표준 및 트랜잭션 기능.

예를 들어, 플레이어가 가상 화폐(코인)를 구입할 수 있는 게임을 개발하려고 합니다.

  • players 테이블에서 각 플레이어는 많은 coins와 구입한 아이템을 포함한 inventory를 갖고 있습니다.
  • items 테이블에서 각 아이템에는 price가 있고, 부울 값 형식으로 사용 가능(available) 여부를 표시합니다.

아이템을 구입하기 위해 이제 하나의 원자적 트랜잭션을 구현할 수 있습니다.

  1. 먼저 아이템이 available하고 플레이어에게 필요한 coins가 있는지 확인합니다.
  2. 이 조건을 충족하면 아이템은 not available하며, 플레이어가 소유(ownedby)한 상태임을 표시합니다.
  3. 그리고 구매한 아이템은 플레이어의 inventory 목록에 추가됩니다.

JavaScript에서 AWS SDK for JavaScript in Node.js를 사용하여 다음과 유사한 코드를 사용합니다.

data = await dynamoDb.transactWriteItems({
    TransactItems: [
        {
            Update: {
                TableName: 'items',
                Key: { id: { S: itemId } },
                ConditionExpression: 'available = :true',
                UpdateExpression: 'set available = :false, ' +
                    'ownedBy = :player',
                ExpressionAttributeValues: {
                    ':true': { BOOL: true },
                    ':false': { BOOL: false },
                    ':player': { S: playerId }
                }
            }
        },
        {
            Update: {
                TableName: 'players',
                Key: { id: { S: playerId } },
                ConditionExpression: 'coins >= :price',
                UpdateExpression: 'set coins = coins - :price, ' +
                    'inventory = list_append(inventory, :items)',
                ExpressionAttributeValues: {
                    ':items': { L: [{ S: itemId }] },
                    ':price': { N: itemPrice.toString() }
                }
            }
        }
    ]
}).promise();

트랜잭션 기능 사용하기

트랜잭션은 단일 리전 DynamoDB 테이블에 대해 활성화되며, 기본적으로 글로벌 테이블에서는 비활성화됩니다.  필요시, 요청하시면 글로벌 테이블에서 트랜잭션을 활성화할 수 있습니다. 그러나, 여러 지역에서 복제가 비동기적으로 수행되지만, 실제로 이러한 작업은 일관됩니다. 다른 지역으로 복제하는 동안 부분적으로 완료된 트랜잭션을 관찰할 수 있을 것입니다. 또한 서로 다른 지역에서 동일한 항목에 대한 동시 쓰기로는 직렬화된 격리를 보장하지 않습니다.

트랜잭션 중에 항목은 잠기지 않습니다. DynamoDB 트랜잭션은 직렬화 가능한 격리를 제공합니다. 트랜잭션이 진행 중일 때 트랜잭션 외부에서 항목이 수정되면 트랜잭션이 취소되고 예외가 발생하며, 예외가 발생한 하나 이상의 항목에 대한 세부 정보가 함께 표시됩니다.

AWS Identity and Access Management (IAM) 정책을 생성할 때 TransactGetItems 및 TransactWriteItems에 대한 새로운 권한은 제공되지 않습니다. 기존의 DynamoDB UpdateItem, PutItem, DeleteItem 및 GetItem 작업으로 트랜잭션 내에서 해당 작업 사용에 대한 권한을 제공합니다. 예를 들어, IAM 사용자에게 PutItem 권한만 있는 경우 하나 이상의 Put으로 트랜잭션을 전송할 수 있지만, 쓰기 세트에 삭제를 추가하는 경우 DeleteItem 권한이 없으므로 작업이 거부됩니다.

트랜잭션 중에 커미트된 작업에 대해 DynamoDB Streams는 새 필드, transaction-id를 트랜잭션에 대한 UUID(Universally Unique Identifier)로 추가합니다. DynamoDB Streams의 순차적이며 정확히 일회적인 시멘틱은 실제로 TransactWriteItems 요청에 대한 모든 업데이트를 트랜잭션 직렬화 순서와 일관된 순서로 전파하도록 보장합니다.

요금, 모니터링 및 가용성

DynamoDB 테이블에 대한 트랜잭션을 활성화하는 경우 추가 비용은 들지 않습니다. 트랜잭션에 포함된 읽기나 쓰기에 대해서만 비용을 지불합니다. DynamoDB는 트랜잭션에서 모든 항목에 대한 기본적인 두 개의 읽기 또는 쓰기를 수행합니다. 하나는 트랜잭션을 준비하는 작업이고 다른 하나는 트랜잭션을 커미트하는 작업입니다. 이 두 개의 기본적인 읽기/쓰기 작업은 CloudWatch 지표로 확인할 수 있습니다. 각 트랜잭션의 읽기는 두 번의 읽기를 수행하고 각 트랜잭션의 쓰기는 두 번의 쓰기를 수행한다고 가정하고 비용, 용량 및 성능 요구 사항을 계획해야 합니다.

이제 DynamoDB 트랜잭션은 모든 상용 지역에서 글로벌하게 사용 가능합니다. 더 자세한 것은 트랜잭션 API 사용 방법을 담은 기술 문서를 참고하세요.

– Danio Poccia;