Logo

AWS CLI로 DynamoDB 다루기

DynamoDB는 AWS에서 제공하는 관리형 NoSQL 데이터베이스 서비스입니다. AWS CLI를 이용하면 간편하게 DynamoDB 테이블을 제어하고 테이터에 접근할 수 있습니다. 이 번 포스팅에서는 자주 사용되는 AWS CLI의 DynamoDB 관련 커맨드을 살펴보도록 하겠습니다.

테이블 생성하기

아직 본인 AWS 계정에 DynamoDB 테이블이 없으신 분들은 일단 테이블부터 생성하셔야 합니다. 예제로 과일 정보를 저장하기 위해서 Fruits 테이블을 생성해보겠습니다. aws dynamodb create-table 커맨드를 사용하며 다음 4가지 옵션을 옵션값을 넘겨줘야 합니다.

  • --table-name: 테이블명 (앞으로 나오는 다른 커맨드들에서도 사용됨)
  • --attribute-definitions: 애트리뷰트(RDB의 열/칼럼/필드 개념) 스키마(이름과 타입) 정의
  • --key-schema: 키 정의. Hash 키는 반드시 필요하며, Range 키는 선택
  • --provisioned-throughput: 테이블 처리량

여기서 주의할 점은 attribute-definitions 옵션에는 키로 사용될 애트리뷰트에 대한 스키마 정의만 필요로 합니다. DynamoDB는 Schemaless 데이터베이스이기 때문에 키 애트리뷰트를 제외한 다른 애트리뷰트의 스키마 정의에는 관심이 없기 때문입니다.

$ aws dynamodb create-table --table-name Fruits \
  --attribute-definitions AttributeName=Id,AttributeType=S \
  --key-schema AttributeName=Id,KeyType=HASH \
  --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
{
    "TableDescription": {
        "AttributeDefinitions": [
            {
                "AttributeName": "Id",
                "AttributeType": "S"
            }
        ],
        "TableName": "Fruits",
        "KeySchema": [
            {
                "AttributeName": "Id",
                "KeyType": "HASH"
            }
        ],
        "TableStatus": "CREATING",
        "CreationDateTime": 1526698654.133,
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 1,
            "WriteCapacityUnits": 1
        },
        (...생략...)
    }
}

응답 값에서 TableStatus 필드값이 CREATING이것에 주목할 필요가 있습니다. aws dynamodb create-table 커맨드는 비동기로 응답하기 때문에 응답 순간에는 아직 테이블이 생성되고 있는 중입니다. 왜냐면 DynamoDB가 테이블을 생성하는데는 약간의 (경험상 수십초? 길어야 1~2분) 시간이 필요하기 때문입니다. 그럼 테이블이 생성이 완료되었다는 것은 어떻게 알 수 있을까요?

테이블 정보 조회하기

aws dynamodb describe-table 커맨드를 사용하면 생성한 테이블의 현재 상태를 포함한 기본적인 테이블 자체의 정보를 조회할 수 있습니다.

$ aws dynamodb describe-table --table-name Fruits
{
    {
        (...생략...)
        "KeySchema": [
            {
                "AttributeName": "Id",
                "KeyType": "HASH"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": 1526698654.133,
        (...생략...)
    }
}

TableStatus 필드값이 ACTIVE로 응답되었으므로 테이블이 활성화 상태입니다. 이 테이블은 이제 데이터를 받아드릴 준비가 되었습니다.

데이터 추가

aws dynamodb put-item 커맨드로 사과에 대한 데이터를 추가해보겠습니다. --item 옵션에 Json 포맷의 문자열을 넘겨주면 되는데, 애트리뷰트 값 부분이 단순 값이 아닌 {"타입": "값"} 형태라는 것에 주의하셔야 합니다. S은 문자열(String) 타입을 의미하고, N은 숫자(Number) 타입을 의미합니다. DynamoDB에서 지원하는 데이터 타입에 대해서 더 알고 싶은 신 분들은 여기를 참고하세요.

$ aws dynamodb put-item --table-name Fruits \
  --item '{"Id": {"S": "A1"}, "Name": {"S": "Apple"}, "Price": {"N": "1000"}}'

데이터 조회

방금 Fruits에 추가한 사과 데이터는 aws dynamodb get-item 커맨드로 조회할 수 있습니다. --key 옵션에 해당 데이터를 생성할 때 사용했던 키 값을 넘겨주면 됩니다.

$ aws dynamodb get-item --table-name Fruits \
  --key '{"Id": {"S": "A1"}}'
{
    "Item": {
        "Id": {
            "S": "A1"
        },
        "Price": {
            "N": "1000"
        },
        "Name": {
            "S": "Apple"
        }
    }
}

데이터 수정

사과 가격을 2배로 올려보겠습니다. 데이터 수정은 데이터를 추가할 때 처럼 aws dynamodb put-item 커맨드로 레코드 전체를 덮어쓰기를 해거나 aws dynamodb update-item 커맨드로 일부 애트리뷰트만 수정할 수 있습니다. --key 옵션으로 수정할 데이터를 지정해주고, --update-expression--expression-attribute-values 옵션으로 수정될 애트리뷰트와 수정될 값을 지정해주면 됩니다.

$ aws dynamodb update-item --table-name Fruits \
  --key '{"Id": {"S": "A1"}}' \
  --update-expression 'SET Price=:Price' \
  --expression-attribute-values '{":Price": {"N": "2000"}}'

데이터 삭제

데이터 삭제는 aws dynamodb delete-item 커맨드를 이용하는데, 데이터 단건 조회처럼 --key 옵션에 삭제할 데이터의 키를 넘겨주면 됩니다.

$ aws dynamodb delete-item --table-name Fruits \
  --key '{"Id": {"S": "A1"}}'

여러 데이터 추가/삭제

AWS CLI는 한 번에 여러 개의 데이터를 추가/삭제할 수 있도록 aws dynamodb batch-write-item 커맨드를 제공합니다. --request-items 옵션을 통해 추가/삭제되는 내용을 넘겨주면 됩니다. 이 커맨드를 이용해서 3개의 과일 레코드를 한 번에 추가해보겠습니다.

$ aws dynamodb batch-write-item --request-items file://fruites.json
{
    "UnprocessedItems": {}
}

--request-items 옵션 값이 너무 길어서 별도의 파일에 저장하고 파일 이름을 넘겼습니다. fruites.json 파일의 내용은 다음과 같습니다.

{
  "Fruits": [
    {
      "PutRequest": {
        "Item": {
          "Id": { "S": "A1" },
          "Name": { "S": "Apple" },
          "Price": { "N": "1000" }
        }
      }
    },
    {
      "PutRequest": {
        "Item": {
          "Id": { "S": "B1" },
          "Name": { "S": "Banana" },
          "Price": { "N": "2000" }
        }
      }
    },
    {
      "PutRequest": {
        "Item": {
          "Id": { "S": "C1" },
          "Name": { "S": "Cherry" },
          "Price": { "N": "5000" }
        }
      }
    }
  ]
}

데이터 쿼리

테이블로 부터 여러 건의 레코드를 키나 인덱스를 기준으로 조회하려면 aws dynamodb query 커맨드를 이용해서 DynamoDB에 쿼리 요청해야합니다. 본 예제 테이블은 Range 키가 없고 별도의 인덱스도 추가해주지 않았기 때문에 Hash 키로만 쿼리를 날릴 수 있습니다.

$ aws dynamodb query --table-name Fruits
  --key-condition-expression 'Id = :Id'
  --expression-attribute-values '{":Id": {"S": "B1"}}'
{
    "Items": [
        {
            "Id": {
                "S": "B1"
            },
            "Price": {
                "N": "2000"
            },
            "Name": {
                "S": "Banana"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

응답 결과에서 ScannedCount 필드는 쿼리 수행을 위해 내부적으로 DynamoDB가 접근한 레코드 수를 의미하고 Count 필드는 최종 응답을 통해 반환된 레코드 수를 의미합니다. 본 예제에서는 별도의 필터를 사용하지 않았기 때문에 1로 일치합니다.

데이터 스캔

aws dynamodb scan 커맨드로 데이터를 스캔을 하면 키나 인덱스가 아닌 다른 일반 애트리뷰트로도 여러 건의 데이터를 조회할 수 있습니다. 대신에 테이블 전체를 스캔하기 때문에 성능이 떨어지며 비용도 비싼 단점이 있습니다. 아래는 3000보다 저렴한 과일을 조회하는 스캔 예제입니다. --filter-expression 옵션에 필터링 조건을 넘기고, --expression-attribute-values 옵션에 조건에서 사용될 값을 넘겨주면 됩니다. 추가적으로 --return-consumed-capacity 옵션을 사용하면 해당 커맨드가 얼마의 테이블 처리량을 소모했는지를 알 수 있어서 스캔 같이 비용이 비쌀 수 있는 커맨드를 날릴 때 유용합니다.

aws dynamodb scan --table-name Fruits \
  --filter-expression 'Price < :Price' \
  --expression-attribute-values '{":Price": {"N": "3000"}}' \
  --return-consumed-capacity TOTAL
{
    "Items": [
        {
            "Id": {
                "S": "B1"
            },
            "Price": {
                "N": "2000"
            },
            "Name": {
                "S": "Banana"
            }
        },
        {
            "Id": {
                "S": "A1"
            },
            "Price": {
                "N": "1000"
            },
            "Name": {
                "S": "Apple"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 3,
    "ConsumedCapacity": {
        "TableName": "Fruits",
        "CapacityUnits": 0.5
    }
}

응답 결과에서 ScannedCountCount 필드를 통해 총 3개의 데이터가 스캔 되었고 그 중 필터링 조건에 맞는 2개의 데이터만 반환되었음을 알 수 있습니다. 이를 위해 해당 테이블의 처리량을 0.5 RCU 만큼 소모했다는 것을 알 수 있습니다. 테이블에 레코드수가 많을 수록 ScannedCountCount 필드 값의 차이는 커지게 됩니다.

테이블 제거

마지막으로 Fruits 테이블을 제거해보록 하겠습니다. aws dynamodb delete-table 커맨드에 --table-name 옵션으로 테이블 이름만 넘겨주면 됩니다.

$ aws dynamodb delete-table --table-name Fruits
{
    "TableDescription": {
        "TableName": "Fruits",
        "TableStatus": "DELETING",
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 1,
            "WriteCapacityUnits": 1
        },
        (...생략...)
    }
}

테이블 생성과 마찬가지로 테이블 삭제도 비동기 커맨드이므로 아직 삭제 작업이 끝나지 않았다는 것을 알려주기 위해 TableStatus 값을 DELETING로 응답합니다. 잠시 후에 aws dynamodb describe-table 커맨드를 날려보시면 테이블이 삭제되었기 때문에 ResourceNotFoundException 예외가 응답될 것입니다.

정리

지금까지 DynamoDB를 다루기 위한 여러 가지 AWS CLI 커맨드와 옵션들을 살펴보았습니다. 커맨드들을 최종 정리를 해보면 다음과 같습니다.

커맨드 용도
aws dynamodb create-table 테이블 생성
aws dynamodb describe-table 테이블 정보 조회
aws dynamodb put-item 데이터 추가
aws dynamodb get-item 데이터 조회
aws dynamodb update-item 데이터 수정
aws dynamodb delete-item 데이터 삭제
aws dynamodb batch-write-item 여러 데이터 추가/삭제
aws dynamodb query 데이터 쿼리
aws dynamodb scan 데이터 스캔
aws dynamodb delete-table 테이블 제거