DynamoDB와 친해지기

공상현 (Kong Sang Hyean)·2024년 2월 12일
0

study

목록 보기
3/4

🖥️ DynamoDB

DynamoDB란?

DynamoDB 공식문서 : https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html

우선 AWS 공식문서 내에서 DynamoDB는 다음과 같이 정의하고 있습니다.

Amazon DynamoDB는 원활한 확장성과 함께 빠르고 예측 가능한 성능을 제공하는 완전 관리형 NoSQL 데이터베이스 서비스입니다.

그 외의 특징을 다음과 같이 나타내고 있습니다.

  • DynamoDB의 분산 데이터베이스 운영 및 확장에 따른 관리 부담을 덜어준다.
  • DB 내 암호화를 제공하여 민감한 데이터 보호와 관련된 운영 부담과 복잡성을 제거한다.
  • 성능 저하 없이 사용 중 테이블의 처리량을 확장하거나 축소할 수 있다.
  • 백업 기능을 제공한다.

DynamoDB를 선택한 이유

프로젝트 개발에 필요한 DB 중 DynamoDB를 고른 이유는 크게 다음과 같이 나열 할 수 있습니다.

  • 개발 중에도 부담없는 요금
  • 서버리스 API(AWS Lamda) 서비스와의 쉬운 운영

우선 DynamoDB은 25GB의 용량과 25개의 읽쓰기 용량 유닛 및 월 2억 건의 요청 무료로 사용할 수 있습니다. 개발하고 있는 사이드 프로젝트 같은 경우 50명 내외로 비교적 적은 인원이 사용할 것을 산정하고 개발하고 있기 때문에 위에서 제공하는 용량 및 요청으로 충분히 서비스를 제공할 수 있다고 생각했습니다. 또한 API를 AWS에서 제공하는 Lamda 서비스에서 서버리스 방식으로 배포하여 운영하고 있기 때문에 같은 프로바이더 서비스를 제공하는 DynamoDB을 사용할 경우 같은 프로바이더 계정으로 한번에 DB와 서버리스를 운영할 수 있다는 점 때문에 DynamoDB를 선택하였습니다.


🤓 테이블과 외부 인덱스 설정하기

테이블 생성

AWS 내에서 테이블을 추가할 때 다음과 같이 나타났습니다.

테이블 이름 (Table Name) : 말 그대로 테이블 이름을 설정해주는 항목입니다.
기본 키 : 파티션 키 (Partition key), 정렬 키 (Sort key)

파티션 키, 정렬 키를 설정할 때 사용할 테이블 내에서 기본적으로 조회 시 가장 중요한 항목을 선택하여 설정하였습니다.

외부 인덱스

API 개발을 하는 도중 테이블 생성 시 설정한 키와 다른 조회 기준으로 테이블 작업을 실행해할 경우가 생겼습니다.
위를 해결하기 위해 DynamoDB 외부 인덱스를 설정하였습니다.

외부 인덱스에 대한 스터디를 진행하면서 크게 다음과 같은 종류가 있다는 것을 알게 되었습니다.

  • Global Secondary Index (GSI) : 기본 테이블의 파티션 키와 정렬 키가 다를 수 있는 인덱스입니다. 글로벌 보조 인덱스는 인덱스에 대한 쿼리가 모든 파티션에 걸쳐 기본 테이블의 모든 데이터에 걸쳐 있을 수 있기 때문에 "글로벌"로 간주됩니다. 글로벌 보조 인덱스에는 크기 제한이 없으며 테이블의 설정과 별도로 읽기 및 쓰기 활동에 대해 자체적으로 프로비저닝된 처리량 설정이 있습니다.
  • Local Secondary Index (LSI) : 기본 테이블과 파티션 키는 동일하지만 정렬 키가 다른 인덱스입니다. 로컬 보조 인덱스는 로컬 보조 인덱스의 모든 파티션이 동일한 파티션 키 값을 갖는 기본 테이블 파티션으로 범위가 지정된다는 점에서 "로컬"입니다. 따라서 하나의 파티션 키 값에 대해 인덱싱된 항목의 총 크기는 10GB를 초과할 수 없습니다. 또한 로컬 보조 인덱스는 인덱싱하는 테이블과 읽기 및 쓰기 활동에 대해 프로비저닝된 처리량 설정을 공유합니다.

저 같은 경우 정렬 키만 다르기 설정하여 테이블 내역을 조회할 예정이기 때문에 Global Secondary Index를 이용하여 외부 인덱스를 추가해놓았습니다.

그 외로 프로비저닝된 처리량 및 오토 스케일링 설정도 있었습니다.


🤓 CRUD 사용하기

아래의 코드는 Node.js + TypeScript를 기반으로 작성되었습니다.

생성한 테이블을 통하여 DynamoDB CRUD 작업을 진행하였습니다.

항목 생성하기 (Create)

테이블 내 항목을 생성하는 경우 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);
  }

항목 불러오기 (Read)

항목을 불러오는 경우 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,
    });
   }
    

항목 수정하기 (Update)

테이블 내 항목을 수정하는 경우 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,
      },
    });
  }

🧐 겪었던 에러

ValidationException: The provided key element does not match the schema

QueryCommand를 외의 PutCommand, GetCommand, UpdateCommand를 사용한 코드를 실행할 때 위와 같은 에러를 만났습니다.
위의 에러가 나왔던 이유는 Command 내의 Key의 Value가 설정한 TableName에서 설정한 테이블 기본 키의 형식이 달라서 나타난 오류입니다. 위를 해결하기 위해서 설정한 기본 키 내의 파티션 키 및 정렬 키의 Key 및 Value를 빠짐 없이 작성하고 나서야 위의 에러를 해결해 낼 수 있었습니다.

profile
개발자 같은 거 합니다. 1인분 하는 개발자로서 살아갈려고 노력 중입니다.

0개의 댓글