2017년 5월 26일 금요일

[AWS] AWS Lambda에서 DynamoDB에 데이터 삽입, 조회, 수정, 삭제 하기.

AWS Lambda에서 DynamoDB에 데이터 삽입, 조회, 수정, 삭제 하기.

이번 포스팅에서는 AWS의 서버리스 컴퓨트 서비스인 Lambda에서, NoSQL 서비스인 DynamoDB에 데이터를 삽입, 조회, 수정, 삭제하는 방법에 대해서 정리해보겠습니다.
Lambda에서는 node.js를 사용했습니다.

1. DynamoDB에서 Table 생성하기

먼저 DynamoDB에 데이터를 넣을 수 있는 Table을 생성합니다.
DynamoDB에서 Table을 생성하는 것은 매우 간단합니다.
중요한 것은 Partition Key가 관계형데이터베이스의 Primary Key라고 생각하시면 되는 것 입니다.
그리고 선택적으로 Sort Key를 추가하면 Partition Key와 Sort Key가 복합으로 Primary Key키로써 테이블 내에서 하나의 항목(Item)을 식별하는데 사용됩니다.
Table을 만들때는 단지, Table의 이름과 Partition Key, Sort Key를 지정해주면 끝납니다.
물론, 더 세세한 설정이 가능하지만 이번 포스팅에서는 기본설정으로 사용하도록 하겠습니다.
(저도 초보자라서 자세한 설정은 아직 지식이 깊지 않아서요..ㅎㅎ)

2. Lambda에서 DynamoDB에 접근하기

두 소제목으로 정리하겠습니다.
첫번째는 Lambda 코드에서 DynamoDB에 데이터를 삽입, 조회, 수정, 삭제하는 함수이고,
두번째는 함수의 인자로 넘길 변수의 메세지 포맷(Json 형식)입니다.

2-1. Lambda 코드

여기서 설명은 코드내에서 주석으로 정리하겠습니다.
'use strict';

console.log('Loading function');

// DynamoDB를 사용하기 위해서 아래 2줄을 꼭 추가시켜줘야합니다.
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();

exports.handler = (event, context, callback) => {
    
    // DynamoDB에 데이터를 조작한 뒤에 그 결과를 받아서 Lambda함수를 return 시킬 콜백함수입니다.
    // 이 예제에서는 처리결과코드(statusCode)와 처리내용(body)를 본 Lambda함수의 결과로 반환합니다.
    const done = (err, res) => callback(null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
    });

    // 아래 2-2에서 설명드리겠지만 저는 이 람다함수를 수행하기 위해서 요청 payload에 method 항목을 넣었습니다.
    // 이 method는 post, get, put, delete 값을 가지고 그에 따라 분기합니다.
    switch (event.method) {
        case 'DELETE':
            // DynamoDB에서 Item을 삭제 시킬 때는 deleteItme 함수를 이용합니다.
            // 함수 호출에 필요한 메세지를 첫번째 인자로 넘기고, 두번째 인자에 결과를 받을 콜백함수를 넣어줍니다.
            // 인자는 모든 함수가 동일합니다. 다만 메세지의 포맷이 조금씩 변경될 뿐입니다. 그 내용은 아래 2-2에서 정리하겠습니다.
            dynamo.deleteItem(event.body, done);
            break;
        case 'GET':
            // (1) Read Item : Key를 알고 있는 한 Item을 가져옵니다.
            dynamo.getItem(event.body, done);

            // (2) Query Data : 조건에 만족하는 일부 Item들만 가져옵니다.
            //dynamo.query(event.body, done);

            // (3) Scan Data : 지정한 테이블의 전체 Item들을 가져옵니다.
            //dynamo.scan(event.body, done);
            break;
        case 'POST':
            // 새로운 Item을 추가할 때는 putItem 함수를 사용합니다.
            dynamo.putItem(event.body, done);
            break;
        case 'PUT':
            // Item의 내용을 수정할 때는 updateItem 함수를 사용합니다.
            dynamo.updateItem(event.body, done);
            break;
        default:
            done(new Error(`Unsupported method`));
    }
};

2-2. 함수의 첫번째 인자로 넘기는 메세지 포맷

Lambda에서 DynamoDB를 조작할 때는 함수에 Json 형식의 메세지를 넘기게 되는데,
삽입, 조회, 수정, 삭제 각 경우에 따라서 메세지에 담아야할 항목들이 조금씩 다릅니다.
이번에는 이 때 각각 어떤 항목이 기본적으로 필요한지 정리하겠습니다.
Lambda함수의 테스트를 위해서 아래와 같은 기본 포맷을 사용했습니다.
method는 제가 Lambda 코드에서 분기 시키기 위해서 넣어 놓은 것이고,
중요한 것은 body항목의 값으로 들어가 있는 부분 입니다.
위에서 제시한 예제에서도 DynamoDB에 이 body부분만 추출해서 인자로 넣습니다.
{
    "method":"POST",
    "body":{...}
}
아래의 코드들은 body부분만 작성한 것이니 주의해주시기 바랍니다.

(1) 삽입(putItem)

{
    "TableName":"{테이블 이름}",
    "Item":{
        "{Partition Key}":"{추가할 값}",
        "{Sort Key}":"{추가할 값}",
        "{기타 추가할 Attribute}":"{추가할 값}"
    }
}
삽입에서 꼭 필요한 항목은 TableName과 Item입니다.
꼭 대소문자 확식하게 구별해주셔야합니다. 안그러면 에러나서 안됩니다.
Partition Key는 필수로 넣어주셔야하고, Sort Key도 설정하셨다면 필수로 넣어주셔야합니다.
그외 넣고싶은 Attribute를 Json 형식으로 마음껏 넣으셔도 됩니다.
참고로, 아시다시피 값이 숫자라면 쌍따옴표로 묶어줄 필요없이 숫자만 기입하셔도 됩니다.
오히려 Partition Key 또는 Sort Key의 자료형을 숫자(Number)로 했는데 숫자값을 쌍따옴표로 묶었다면 에러가 발생합니다.

(2) 조회

조회는 3가지가 있습니다.
Key를 알고있어서 바로 딱 한 Item만 조회하는 방법, Query를 이용해서 일부 Item들을 조회하는 방법, 전체 Item을 조회하는 방법입니다.
명명하는 것을 구분하기 위하여, 한 Item만 가져오는 것을 Read Item, 일부 Item들을 가져오는 것을 Query Data, 전체 Item들을 가져오는 것을 Scan Data라고 하겠습니다.
(1) Read Item
{
    "TableName": "{테이블 이름}",
    "Key": {
        "{Partition Key}":"{찾을 값}",
        "{Sort Key}":"{찾을 값}"
    }
}
Key를 알고 있는 상태에서 해당 Key에 해당하는 특정 Item만 가져오기를 원할 때는 getItem()함수를 사용합니다.
그리고 요청에는 TableName과 Key 정보만 넘기면 됩니다.
(2) Query Data
{
    "TableName": "{테이블 이름}",
    "KeyConditionExpression":"{찾으려는 Partition Key} = :{변수명1} and {찾으려는 Sort Key} between :{변수명2} and :{변수명3}",
    "ExpressionAttributeValues" : {
        ":{변수명1}":"{찾을 값1}",
        ":{변수명2}":"{찾을 값2}",
        ":{변수명3}":"{찾을 값3}"
    }
}
특정 한개의 Item이 아니라 조건식을 이용해서 조건에 해당하는 모든 Item들을 조회하고자 할때는 query()함수를 사용합니다.
여기서는 중요한 점이, Partition Key는 오직 등식 조건(=)만 가능하다는 것입니다. 그리고 Sort Key에 비교 연산자 사용이 가능합니다. Sort Key에 사용 가능한 비교 연산자는 아래 링크에서 확인 가능합니다.
(링크 : http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions)
참고로, Query를 날렸는데 Key명이 예약어라서 오류가 난다면 ExpressionAttributeNames에 대해 알아보시기 바랍니다.
추가적으로, 일반 Attribute를 사용하여 Query를 날리고 싶을 때는, 해당 Attribute를 GSI(Global Secondary Indexes)로 설정하면 됩니다.
GSI에 설정하고 나면, 위 json형식에서 단지 IndexName만 추가하면 됩니다.
{
    "TableName": "{테이블 이름}",
    "IndexName": "{GSI생성 시에 설정한 Index 이름}",
    "KeyConditionExpression":"{찾으려는 Partition Key} = :{변수명1} and {찾으려는 Sort Key} between :{변수명2} and :{변수명3}",
    "ExpressionAttributeValues" : {
        ":{변수명1}":"{찾을 값1}",
        ":{변수명2}":"{찾을 값2}",
        ":{변수명3}":"{찾을 값3}"
    }
}
(3) Scan Data
{
    "TableName": "{테이블 이름}"
}
Table의 모든 Item을 조회할 때는 scan()함수를 사용합니다.
그리고 scan할때는 기본적으로 TableName만 지정하면 해당 Table의 모든 Item을 조회할 수 있습니다.
선택적으로 Filter를 추가할 수는 있습니다.
{
    "TableName": "{테이블 이름}",
    "FilterExpression":"{찾으려는 Attribute} between :{변수명1} and :{변수명2}",
    "ExpressionAttributeValues" : {
        ":{변수명1}":"{찾을 값1}",
        ":{변수명2}":"{찾을 값2}"
    }
}
Filter를 이용하면 일부 Item만 조회하는게 가능한데, 이는 Query Data와 유사합니다.
다만 차이점이 있는데, 첫째, Key 뿐만 아니라 다른 일반 Attribute로도 조회가 가능하다는 점. 둘째, Query Data에서는 Partition Key에 등식 조건(=)만 사용 가능했는데, Scan Data에서는 Filter를 이용하면 Partition Key에 비교 연산자를 사용하여 일부 Item만 조회하는게 가능합니다.
여기서 사용할 수 있는 비교 연산자는 Query Data에서 Sort Key에 적용할 수 있는 것과 동일 한 것 같습니다.

(3) 수정

{
    "TableName":"{테이블 이름}",
    "Key":{
        "{Partition Key}":"{찾을 값}",
        "{Sort Key}":"{찾을 값}"
    },
    "UpdateExpression":"set {변경할 Attribute1} = :{변수명1}, {변경할 Attribute2} = :{변수명2}",
    "ExpressionAttributeValues":{
        ":{변수명1}":"{변경할 값1}",
        ":{변수명2}":"{변경할 값2}"
    },
    "ReturnValues":"UPDATED_NEW"
}
수정에서는 필수로 넣어줘야하는 항목이 4개입니다.
TableNameKeyUpdateExpressionExpressionAttributeValues입니다.
TableName은 수정을 원하는 테이블의 이름이며, Key는 수정할 데이터를 찾기 위한 Partition Key와 Sort Key를 알려주는 곳입니다.
UpdateExpression은 변경할 데이터의 Attribute를 지정하는 곳입니다.
ExpressionAttributeValues에서 변수들과 값들을 매칭시킵니다.
ReturnValues는 선택 항목인데, 이 항목이 없으면 수정 요청이 성공해도 아무런 응답값이 없지만, 이 항목의 값을 UPDATED_NEW로 하면 수정한 값이 응답으로 되돌아 옵니다.

(4) 삭제

{
    "TableName":"{테이블 이름}",
    "Key":{
        "{Partition Key}":"{찾을 값}",
        "{Sort Key}":"{찾을 값}"
    }
}
삭제는 테이블 이름과 키만 넘기면 바로 삭제 됩니다. Sort Key를 설정하지 않았다면 Partition Key만 입력하시면 됩니다.
지금까지 읽어주셔서 감사합니다.
여러분의 정보 습득에 도움이 되었길 바랍니다.
혹여, 틀린 내용이나 보충되야할 내용이 있다면 댓글 달아주시면 바로 확인하고 보완하도록 하겠습니다.
감사합니다.

참고 링크
AWS Doc
AWS DynamoDB Query 상세
AWS DynamoDB Scan 상세

댓글 없음:

댓글 쓰기