Node.js의 DynamoDB TransactWriteItems (AWS SDK v3)
성공한 TransactWriteItemsCommand는 사실상 아무것도 알려 주지 않습니다. 항목도 속성도 없는 빈 응답입니다. 필요한 모든 것은 예외에 실려 있으므로, SDK v3에서는 아래 catch 블록이 진짜 API 표면이며 거기에 무엇이 떨어지는지 정확히 알아 둘 만합니다. (애초에 트랜잭션이 옳은 선택인지에 대해서는 DynamoDB 트랜잭션을 보세요.)
코드
import {DynamoDBClient, TransactWriteItemsCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
// Move one award between two songs — atomically. If the first song has no
// award to give, NEITHER update happens.
const command = new TransactWriteItemsCommand({
TransactItems: [
{
Update: {
TableName: 'Music',
Key: {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'Cubano Chant'}},
UpdateExpression: 'SET #upd0 = #upd0 - :one',
ConditionExpression: '#upd0 >= :one',
ExpressionAttributeNames: {'#upd0': 'Awards'},
ExpressionAttributeValues: {':one': {N: '1'}}
}
},
{
Update: {
TableName: 'Music',
Key: {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'A Mis Abuelos'}},
UpdateExpression: 'SET #upd0 = if_not_exists(#upd0, :zero) + :one',
ExpressionAttributeNames: {'#upd0': 'Awards'},
ExpressionAttributeValues: {':one': {N: '1'}, ':zero': {N: '0'}}
}
}
]
});
try {
await client.send(command);
console.log('Transaction committed');
} catch (err) {
if (err.name === 'TransactionCanceledException') {
// One reason per action, in TransactItems order. 'None' means that action
// was fine — some OTHER action sank the transaction.
const codes = (err.CancellationReasons ?? []).map((r) => r.Code);
console.log('Transaction canceled:', codes); // e.g. ['ConditionalCheckFailed', 'None']
} else {
throw err;
}
}설명
TransactItems—Put,Update,Delete,ConditionCheck작업의 순서 있는 배열입니다. 이 순서는 실행 순서가 아니지만(트랜잭션은 원자적입니다), 실패 사유가 돌아오는 순서_이며_ 그것이 이 순서에 신경 써야 하는 유일한 이유입니다. 상한은 아래에서 다룹니다.- v3가 실제로 던지는 것. 잡힌 객체가 자체적으로 가진 속성은
$fault,$retryable,$metadata,name,CancellationReasons,message,__type입니다.err.code는 없습니다. 분기해야 할 문자열은err.name이고,err.$metadata에는httpStatusCode: 400과 함께attempts: 1이 담겨 있어 SDK가 취소를 조용히 재시도하지 않았음을 알 수 있습니다. CancellationReasons는 위치 기반이고 듬성듬성합니다. 위 트랜잭션에서는[{"Code":"ConditionalCheckFailed","Message":"The conditional request failed"},{"Code":"None"}]로 도착합니다.None항목에는Message속성이 아예 없으므로,err.CancellationReasons.map((r) => r.Message.trim())은 하필 성공한 작업들에서 여러분의 오류 처리기 안에서 예외를 던집니다.ReturnValuesOnConditionCheckFailure: 'ALL_OLD'는 해당 작업의 사유에Code와Message보다 앞서Item을 원시 DynamoDB JSON으로 덧붙입니다. 패배한 항목의 속성이 공짜로 돌아오며, 그 대안은 이미 경합에서 진 뒤에GetItem을 한 번 더 하는 것입니다.err.name검사에는 구멍이 하나 있고, 그것이 무엇인지 알아 둘 만합니다. 두 작업을 같은 항목에 겨냥하면 DynamoDB는Transaction request cannot include multiple operations on one item메시지와 함께ValidationException으로 답하며, 시도된 것이 없으므로CancellationReasons는 전혀 없습니다. 위의else { throw err }분기가 그것을 다시 던집니다. 이것은 버그가 아니라 올바른 동작이지만, 구조적 실수는 결코 여러분의 취소 로깅에 닿지 않는다는 뜻이기도 합니다.- v3는 여러분이 생략해도 이미
ClientRequestToken을 보냅니다. 직렬화된 본문을 캡처해 보면 전송 구간에 새 UUID가 실려 있고, 같은 명령 객체로send()를 두 번 호출하면 서로 다른 토큰 두 개가 나갔습니다. 즉 이 토큰은 진행 중인 호출 하나를 보호할 뿐 여러분의 재시도 루프를 보호하지 않습니다. 잡아서 다시 보내면 새 토큰이 붙고 멱등성은 없습니다. 재시도가 프로세스 경계를 넘을 수 있다면 직접 토큰을 제공하세요. 파라미터를 바꾼 채 재사용하면 조용한 이중 적용 대신IdempotentParameterMismatch가 나옵니다. - 별도의 코드 경로가 필요한 것은 하나뿐입니다.
TransactionConflict는 동시에 실행된 다른 트랜잭션이 여러분의 항목 중 하나를 붙잡고 있었다는 뜻이므로,ConditionalCheckFailed에서는 결코 옳지 않은 백오프 재시도가 여기서는 올바른 대응입니다. 나머지는 TransactionCanceledException 페이지에서 해독합니다. - 비용 — 트랜잭션의 모든 항목은 내부적으로 두 번 기록되므로(준비 후 커밋), 일반 쓰기의 약 2배 쓰기 용량을 잡으세요. 단일 항목 조건부 쓰기는 그 절반 비용으로 한 항목에 대한 원자성을 줍니다.
어느 한도에 먼저 걸리나요
100개 작업 상한과 4 MB 상한은 서로 독립적이며, 사람들을 놀라게 하는 것은 바이트 쪽입니다. 카운터를 백 번 증가시키는 것은 아무것도 아니지만, 뚱뚱한 항목 열두 개만으로도 총합 한도를 소진할 수 있습니다. 몇 개의 작업을 묶을지 정하기 전에 DynamoDB 항목 크기 계산기로 대표적인 항목을 재 보세요. 조건을 작성하는 동안 작업이 건드릴 항목을 읽어 보려면 DynoTable을 다운로드하세요.
관련 예제
- Python의 DynamoDB TransactWriteItems — boto3로 하는 동일한 트랜잭션.
- AWS CLI로 하는 DynamoDB TransactWriteItems — 셸에서 하는 동일한 트랜잭션.
- Node.js의 DynamoDB 조건부 쓰기 — 2배 비용 없이 얻는 단일 항목 원자성.
- DynamoDB 트랜잭션 — 격리, 멱등성, 그리고 트랜잭션이 값어치를 하는 시점.
- DynamoDB TransactionCanceledException — 모든 취소 사유 코드 해독.
- "Too many actions in a TransactWriteItems call" — 트랜잭션의 100개 작업 및 4 MB 한도.
- "Transaction request cannot include multiple operations on one item" — 트랜잭션당 항목마다 작업 하나.
참고 자료
- TransactWriteItems — Amazon DynamoDB API Reference
- Amazon DynamoDB transactions: how it works — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
위에 링크된 공식 AWS 문서를 기준으로 2026-07-28에 마지막으로 검증했습니다.