DynamoDB 공식문서 : https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html
우선 AWS 공식문서 내에서 DynamoDB는 다음과 같이 정의하고 있습니다.
Amazon DynamoDB는 원활한 확장성과 함께 빠르고 예측 가능한 성능을 제공하는 완전 관리형 NoSQL 데이터베이스 서비스입니다.
그 외의 특징을 다음과 같이 나타내고 있습니다.
프로젝트 개발에 필요한 DB 중 DynamoDB를 고른 이유는 크게 다음과 같이 나열 할 수 있습니다.
우선 DynamoDB은 25GB의 용량과 25개의 읽쓰기 용량 유닛 및 월 2억 건의 요청 무료로 사용할 수 있습니다. 개발하고 있는 사이드 프로젝트 같은 경우 50명 내외로 비교적 적은 인원이 사용할 것을 산정하고 개발하고 있기 때문에 위에서 제공하는 용량 및 요청으로 충분히 서비스를 제공할 수 있다고 생각했습니다. 또한 API를 AWS에서 제공하는 Lamda 서비스에서 서버리스 방식으로 배포하여 운영하고 있기 때문에 같은 프로바이더 서비스를 제공하는 DynamoDB을 사용할 경우 같은 프로바이더 계정으로 한번에 DB와 서버리스를 운영할 수 있다는 점 때문에 DynamoDB를 선택하였습니다.
AWS 내에서 테이블을 추가할 때 다음과 같이 나타났습니다.
테이블 이름 (Table Name) : 말 그대로 테이블 이름을 설정해주는 항목입니다.
기본 키 : 파티션 키 (Partition key), 정렬 키 (Sort key)
파티션 키, 정렬 키를 설정할 때 사용할 테이블 내에서 기본적으로 조회 시 가장 중요한 항목을 선택하여 설정하였습니다.
API 개발을 하는 도중 테이블 생성 시 설정한 키와 다른 조회 기준으로 테이블 작업을 실행해할 경우가 생겼습니다.
위를 해결하기 위해 DynamoDB 외부 인덱스를 설정하였습니다.
외부 인덱스에 대한 스터디를 진행하면서 크게 다음과 같은 종류가 있다는 것을 알게 되었습니다.
저 같은 경우 정렬 키만 다르기 설정하여 테이블 내역을 조회할 예정이기 때문에 Global Secondary Index를 이용하여 외부 인덱스를 추가해놓았습니다.
그 외로 프로비저닝된 처리량 및 오토 스케일링 설정도 있었습니다.
아래의 코드는 Node.js + TypeScript를 기반으로 작성되었습니다.
생성한 테이블을 통하여 DynamoDB CRUD 작업을 진행하였습니다.
테이블 내 항목을 생성하는 경우 PutCommand를 활용하여 생성하였습니다.
import { PutCommand } from "@aws-sdk/lib-dynamodb";
/*...*/
private readonly repository = Repository.instance();
async PutCommand(dto: any) {
const { client } = this.repository;
const cmd = new PutCommand({
TableName: "Table.name",
Item: dto,
});
return client.send(cmd);
}
항목을 불러오는 경우 GetCommand와 QueryCommand를 이용하여 각 항목을 불러왔습니다.
QueryCommand를 이용할 경우 기본으로 설정된 키 외의 외부 인덱스를 활용하여 항목을 불러올 수 있었습니다.
import { GetCommand, QueryCommand } from "@aws-sdk/lib-dynamodb";
/*...*/
private readonly repository = Repository.instance();
async GetCommand(partitionKey: string, sortKey: string): Promise<any[] | undefined> {
const { client } = this.repository;
const cmd = new GetCommand({
TableName: "Table.name",
Key: {
partitionKey: partitionKey,
sortKey: sortKey,
},
});
}
async QueryCommand(partitionKey: string, sortKey: string): Promise<any[] | undefined> {
const { client } = this.repository;
const cmd = new QueryCommand({
TableName: "Table.name",
IndexName: "secondary-index",
KeyConditionExpression: "#attrName1 = :attrValue1, #attrName2 = :attrValue2",
ExpressionAttributeNames: {
"#attrName1": "partitionKey",
"#attrName2": "sortKey",
},
ExpressionAttributeValues: {
":attrValue1": partitionKey,
":attrValue2": sortKey,
},
ScanIndexForward: false,
});
}
테이블 내 항목을 수정하는 경우 UpdateCommand를 활용하여 생성하였습니다.
import { UpdateCommand } from "@aws-sdk/lib-dynamodb";
/*...*/
async UpdateCommand(dto: any) {
const { client } = this.repository;
const cmd = new UpdateCommand({
TableName: "Table.name",
Key: {
partitionKey: dto.partitionKey,
sortKey: dto.sortKey,
},
UpdateExpression: "set updateKey = :updateKey",
ExpressionAttributeValues: {
":updateKey": dto.updateKey,
},
});
}
QueryCommand를 외의 PutCommand, GetCommand, UpdateCommand를 사용한 코드를 실행할 때 위와 같은 에러를 만났습니다.
위의 에러가 나왔던 이유는 Command 내의 Key의 Value가 설정한 TableName에서 설정한 테이블 기본 키의 형식이 달라서 나타난 오류입니다. 위를 해결하기 위해서 설정한 기본 키 내의 파티션 키 및 정렬 키의 Key 및 Value를 빠짐 없이 작성하고 나서야 위의 에러를 해결해 낼 수 있었습니다.