기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
AWS AppSync는 단일 리전의 하나 이상의 테이블에서 Amazon DynamoDB 트랜잭션 작업 사용을 지원합니다. 지원되는 작업은 TransactGetItems
, TransactWriteItems
입니다. AWS AppSync에서 이러한 기능을 사용하여 다음과 같은 작업을 수행할 수 있습니다.
-
단일 쿼리에서 키 목록을 전달하고 테이블의 결과 반환
-
단일 쿼리의 하나 이상의 테이블에서 레코드 읽기
-
트랜잭션의 레코드를 하나 이상의 테이블에 전부 또는 전무 방식으로 기록
-
일부 조건이 충족되면 트랜잭션 실행
권한
다른 해석기와 마찬가지로 AWS AppSync에서 데이터 소스를 생성하고 역할을 생성하거나 기존 역할을 사용해야 합니다. 트랜잭션 작업에는 DynamoDB 테이블에 대한 여러 권한이 필요하기 때문에 읽기 또는 쓰기 작업에 대해 구성된 역할 권한을 부여해야 합니다.
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:accountId:table/TABLENAME", "arn:aws:dynamodb:region:accountId:table/TABLENAME/*" ] } ] }
참고
역할은 AWS AppSync의 데이터 소스에 연결되며 필드의 해석기는 데이터 소스에 대해 호출됩니다. DynamoDB에 대해 가져오도록 구성된 데이터 소스에는 구성을 간단하기 유지하기 위해 지정된 테이블이 하나뿐입니다. 따라서 단일 해석기에서 여러 테이블에 대해 트랜잭션 작업을 수행하는 경우(고급 작업임) 데이터 원본 액세스에 대한 역할을 해석기가 상호 작용하는 모든 테이블에 부여해야 합니다. IAM 정책의 리소스 필드에서 부여할 수 있습니다. 테이블에 대한 트랜잭션 호출의 구성은 해석기 코드에서 수행되는데, 이 내용은 아래에서 설명합니다.
데이터 소스
간단하게 설명하기 위해 이 자습서에서 사용되는 모든 해석기에 대해 동일한 데이터 원본을 사용합니다.
accountNumber
를 파티션 키로 사용하는 savingAccounts 및 checkingAccounts라는 두 개의 테이블과 transactionId
를 파티션 키로 사용하는 transactionHistory 테이블이 있습니다. 아래 CLI 명령을 사용하여 테이블을 만들 수 있습니다. region
을 해당 리전으로 바꿔야 합니다.
CLI 사용
aws dynamodb create-table --table-name savingAccounts \
--attribute-definitions AttributeName=accountNumber,AttributeType=S \
--key-schema AttributeName=accountNumber,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--table-class STANDARD --region region
aws dynamodb create-table --table-name checkingAccounts \
--attribute-definitions AttributeName=accountNumber,AttributeType=S \
--key-schema AttributeName=accountNumber,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--table-class STANDARD --region region
aws dynamodb create-table --table-name transactionHistory \
--attribute-definitions AttributeName=transactionId,AttributeType=S \
--key-schema AttributeName=transactionId,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--table-class STANDARD --region region
AWS AppSync 콘솔의 데이터 소스에서 새 DynamoDB 데이터 소스를 생성하고 이름을 TransactTutorial으로 지정합니다. savingAccounts를 테이블로 선택합니다(단, 트랜잭션을 사용할 때 특정 테이블은 중요하지 않음). 새 역할과 데이터 소스를 만들도록 선택합니다. 데이터 소스 구성을 검토하여 생성된 역할의 이름을 확인할 수 있습니다. IAM 콘솔에서 데이터 소스가 모든 테이블과 상호 작용하도록 허용하는 인라인 정책을 추가할 수 있습니다.
region
과 accountID
를 리전 및 계정 ID로 바꿉니다:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:UpdateItem"
],
"Effect": "Allow",
"Resource": [
"arn:aws:dynamodb:region:accountId:table/savingAccounts",
"arn:aws:dynamodb:region:accountId:table/savingAccounts/*",
"arn:aws:dynamodb:region:accountId:table/checkingAccounts",
"arn:aws:dynamodb:region:accountId:table/checkingAccounts/*",
"arn:aws:dynamodb:region:accountId:table/transactionHistory",
"arn:aws:dynamodb:region:accountId:table/transactionHistory/*"
]
}
]
}
트랜잭션
이 예에서 컨텍스트는 전형적인 은행 거래이며 여기서 다음을 위해 TransactWriteItems
를 사용합니다.
-
저축 계좌에서 당좌 예금 계좌로 돈을 이체
-
각 트랜잭션에 대한 새 트랜잭션 레코드 생성
그런 다음 TransactGetItems
를 사용하여 저축 계좌와 당좌 예금 계좌의 세부 정보를 검색합니다.
주의
충돌 감지 및 해결과 함께 사용할 때는 TransactWriteItems
가 지원되지 않습니다. 오류가 발생하지 않도록 해당 설정을 비활성화해야 합니다.
GraphQL 스키마는 다음과 같이 정의합니다.
type SavingAccount { accountNumber: String! username: String balance: Float } type CheckingAccount { accountNumber: String! username: String balance: Float } type TransactionHistory { transactionId: ID! from: String to: String amount: Float } type TransactionResult { savingAccounts: [SavingAccount] checkingAccounts: [CheckingAccount] transactionHistory: [TransactionHistory] } input SavingAccountInput { accountNumber: String! username: String balance: Float } input CheckingAccountInput { accountNumber: String! username: String balance: Float } input TransactionInput { savingAccountNumber: String! checkingAccountNumber: String! amount: Float! } type Query { getAccounts(savingAccountNumbers: [String], checkingAccountNumbers: [String]): TransactionResult } type Mutation { populateAccounts(savingAccounts: [SavingAccountInput], checkingAccounts: [CheckingAccountInput]): TransactionResult transferMoney(transactions: [TransactionInput]): TransactionResult }
TransactWriteItems - 계좌 정보 채우기
계좌 간에 돈을 이체하려면 테이블에 세부 정보를 채워 넣어야 합니다. 이를 위해 GraphQL 작업 Mutation.populateAccounts
를 사용하겠습니다.
스키마 섹션에서 Mutation.populateAccounts
작업 옆에 있는 연결을 클릭합니다. TransactTutorial
데이터 소스를 선택한 다음 생성을 선택합니다.
다음 코드를 사용합니다.
import { util } from '@aws-appsync/utils'
export function request(ctx) {
const { savingAccounts, checkingAccounts } = ctx.args
const savings = savingAccounts.map(({ accountNumber, ...rest }) => {
return {
table: 'savingAccounts',
operation: 'PutItem',
key: util.dynamodb.toMapValues({ accountNumber }),
attributeValues: util.dynamodb.toMapValues(rest),
}
})
const checkings = checkingAccounts.map(({ accountNumber, ...rest }) => {
return {
table: 'checkingAccounts',
operation: 'PutItem',
key: util.dynamodb.toMapValues({ accountNumber }),
attributeValues: util.dynamodb.toMapValues(rest),
}
})
return {
version: '2018-05-29',
operation: 'TransactWriteItems',
transactItems: [...savings, ...checkings],
}
}
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons)
}
const { savingAccounts: sInput, checkingAccounts: cInput } = ctx.args
const keys = ctx.result.keys
const savingAccounts = sInput.map((_, i) => keys[i])
const sLength = sInput.length
const checkingAccounts = cInput.map((_, i) => keys[sLength + i])
return { savingAccounts, checkingAccounts }
}
해석기를 저장하고 AWS AppSync 콘솔의 쿼리 섹션으로 이동하여 계정을 채웁니다.
다음 변형을 실행합니다.
mutation populateAccounts {
populateAccounts (
savingAccounts: [
{accountNumber: "1", username: "Tom", balance: 100},
{accountNumber: "2", username: "Amy", balance: 90},
{accountNumber: "3", username: "Lily", balance: 80},
]
checkingAccounts: [
{accountNumber: "1", username: "Tom", balance: 70},
{accountNumber: "2", username: "Amy", balance: 60},
{accountNumber: "3", username: "Lily", balance: 50},
]) {
savingAccounts {
accountNumber
}
checkingAccounts {
accountNumber
}
}
}
하나의 뮤테이션으로 3개의 저축 계좌와 3개의 당좌 예금 계좌 정보를 채웠습니다.
DynamoDB 콘솔을 사용하여 데이터가 savingAccounts 및 checkingAccounts 테이블 모두에 표시되는지 확인합니다.
TransactWriteItems - 송금
다음 코드를 사용하여 transferMoney
뮤테이션에 해석기를 연결합니다. 이체할 때마다 당좌 예금 계좌와 저축 계좌 모두에 성공 한정자가 필요하고 거래의 이체를 추적해야 합니다.
import { util } from '@aws-appsync/utils'
export function request(ctx) {
const transactions = ctx.args.transactions
const savings = []
const checkings = []
const history = []
transactions.forEach((t) => {
const { savingAccountNumber, checkingAccountNumber, amount } = t
savings.push({
table: 'savingAccounts',
operation: 'UpdateItem',
key: util.dynamodb.toMapValues({ accountNumber: savingAccountNumber }),
update: {
expression: 'SET balance = balance - :amount',
expressionValues: util.dynamodb.toMapValues({ ':amount': amount }),
},
})
checkings.push({
table: 'checkingAccounts',
operation: 'UpdateItem',
key: util.dynamodb.toMapValues({ accountNumber: checkingAccountNumber }),
update: {
expression: 'SET balance = balance + :amount',
expressionValues: util.dynamodb.toMapValues({ ':amount': amount }),
},
})
history.push({
table: 'transactionHistory',
operation: 'PutItem',
key: util.dynamodb.toMapValues({ transactionId: util.autoId() }),
attributeValues: util.dynamodb.toMapValues({
from: savingAccountNumber,
to: checkingAccountNumber,
amount,
}),
})
})
return {
version: '2018-05-29',
operation: 'TransactWriteItems',
transactItems: [...savings, ...checkings, ...history],
}
}
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons)
}
const tInput = ctx.args.transactions
const tLength = tInput.length
const keys = ctx.result.keys
const savingAccounts = tInput.map((_, i) => keys[tLength * 0 + i])
const checkingAccounts = tInput.map((_, i) => keys[tLength * 1 + i])
const transactionHistory = tInput.map((_, i) => keys[tLength * 2 + i])
return { savingAccounts, checkingAccounts, transactionHistory }
}
이제 AWS AppSync 콘솔의 쿼리 섹션으로 이동하여 다음과 같이 transferMoney 변형을 실행합니다.
mutation write {
transferMoney(
transactions: [
{savingAccountNumber: "1", checkingAccountNumber: "1", amount: 7.5},
{savingAccountNumber: "2", checkingAccountNumber: "2", amount: 6.0},
{savingAccountNumber: "3", checkingAccountNumber: "3", amount: 3.3}
]) {
savingAccounts {
accountNumber
}
checkingAccounts {
accountNumber
}
transactionHistory {
transactionId
}
}
}
하나의 변형으로 3건의 은행 거래를 보냈습니다. DynamoDB 콘솔을 사용하여 데이터가 savingAccounts, checkingAccounts 및 transactionHistory 테이블에 표시되는지 확인합니다.
TransactGetItems - 계좌 검색
한 번의 트랜잭션 요청으로 저축 계좌와 당좌 예금 계좌의 세부 정보를 검색하기 위해 스키마의 Query.getAccounts
GraphQL 작업에 해석기를 연결하겠습니다. 연결을 선택하고 자습서 시작 부분에서 생성한 TransactTutorial
데이터 소스를 선택합니다. 다음 코드를 사용합니다.
import { util } from '@aws-appsync/utils'
export function request(ctx) {
const { savingAccountNumbers, checkingAccountNumbers } = ctx.args
const savings = savingAccountNumbers.map((accountNumber) => {
return { table: 'savingAccounts', key: util.dynamodb.toMapValues({ accountNumber }) }
})
const checkings = checkingAccountNumbers.map((accountNumber) => {
return { table: 'checkingAccounts', key: util.dynamodb.toMapValues({ accountNumber }) }
})
return {
version: '2018-05-29',
operation: 'TransactGetItems',
transactItems: [...savings, ...checkings],
}
}
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons)
}
const { savingAccountNumbers: sInput, checkingAccountNumbers: cInput } = ctx.args
const items = ctx.result.items
const savingAccounts = sInput.map((_, i) => items[i])
const sLength = sInput.length
const checkingAccounts = cInput.map((_, i) => items[sLength + i])
return { savingAccounts, checkingAccounts }
}
해석기를 저장하고 AppSync AWS 콘솔의 쿼리 섹션으로 이동합니다. 저축 계좌와 당좌 예금 계좌를 검색하려면 다음 쿼리를 실행합니다.
query getAccounts {
getAccounts(
savingAccountNumbers: ["1", "2", "3"],
checkingAccountNumbers: ["1", "2"]
) {
savingAccounts {
accountNumber
username
balance
}
checkingAccounts {
accountNumber
username
balance
}
}
}
AWS AppSync를 사용하여 DynamoDB 트랜잭션을 사용하는 방법을 보여드렸습니다.