관념과 사고

이번 글에서는 Amazon Web Service(AWS) 에서 DynamoDB를 사용하는 방법을 Python을 이용해서 다루도록 하겠습니다.

처음에 AWS Python 카테고리에서 DynamoDB를 다루고자 했던 것은 아니였지만, 이번 회사에서 기술보고서를 작성하는 과정에 있어서 주제를 DynamoDB를 하다 보니까 블로그에도 같이 다루는 것이 좋을 것 같아서 올려봅니다.


2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #1. 소개

2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #2. 테이블 관리

2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #3. 항목 관리


이번 글은 지난 글에 이어서 AWS SDK for Python인 Boto3 를 사용한 DynamoDB의 항목(Items) 호출을 위한 Query & Scan에 대해서 다루어보도록 하겠습니다.

모든 내용은 AWS의 Boto3 Documentation에 있는 내용이며, 번역자료가 없기 때문에 제가 직접 실습하면서 나타내도록 하겠습니다.


원본 문서: http://boto3.readthedocs.io/en/latest/guide/


영어 문서이므로 참고하시기 바랍니다.


1. Query & Scan 

두 가지 모두 DynamoDB의 항목 호출을 위한 기능이지만, 사용 용도는 약간 차이가 있습니다.

Query는 특정 값을 검색했을 때 나타나는 결과를 조회할 때 사용됩니다. 예제에서는 하나의 항목만 반환하지만, get_items() 함수와 기능은 비슷하지만, get_items()가 단순히 키를 지정했을 때의 값을 가져오는 것이지만, Query는 더욱 자세한 조건을 통해서 값을 가져오는 것이 가능합니다.

Scan은 Query와는 다르게 특정 값을 지정해서 불러올 수도 있지만, 주 용도는 호출하고자 하는 값의 범위를 검색 조건으로 할 때 사용됩니다. 내부 속성으로는 FilterExpression을 사용하며, 이는 즉 필터링을 위한 용도로 보는 것이 맞을 것입니다.

Query & Scan을 사용하기 위해서는 boto3를 import하는 것 외에도 추가 클래스를 호출해야 합니다.

추가 클래스는 boto3.dynamodb.conditions.Key와 boto3.dynamodb.conditions.Attr 클래스로, 호출 방법은 아래와 같습니다.

from boto3.dynamodb.conditions import Key, Attr

import boto3 바로 밑에 작성하면 아무 문제 없이 클래스 import가 가능합니다.


아래 Query & Scan을 위한 기본 예제 테이블은 users 테이블로 할 것이며, 해당 테이블의 항목은 아래와 같습니다.

항목의 Address가 내재된 속성(Nested Attributes)들을 포함하고 있으므로, 각 항목 별 값을 나타내면 다음과 같습니다.


 


이 점을 참고하시고 아래 예제를 실행한 결과를 보시면 더욱 이해가 될 수 있을 것입니다.


2. Query

Query 예제는 아래와 같으며, username 파티션 키 값이 'johndoe'의 값을 가진 항목(Equal: EQ)을 조회하는 내용입니다.

당연히 import 에서 클래스 로드까지 모두 마친 상태입니다.

response = table.query(

    KeyConditionExpression=Key('username').eq('johndoe')

)

items = response['Items']

print(items)

결과는 johndoe의 항목이 호출됩니다.


3. Scan

Scan 첫번째 예제입니다. age 속성의 값이 27보다 작을 때 (Lower Than: LT) 의 내용입니다.

response = table.scan(

    FilterExpression=Attr('age').lt(27)

)

items = response['Items']

print(items)

 

결과는 johndoe와 bobsmith의 항목이 호출됩니다.



Scan 두번째 예제입니다. 조건이 조금은 더 복잡해졌습니다.

first_name의 값이 'J'로 시작(Begins_with)하고, account_type이 'super_user'와 동일할 때의 내용입니다.

response = table.scan(

    FilterExpression=Attr('first_name').begins_with('J') & Attr('account_type').eq('super_user')

)

items = response['Items']

print(items)

 

결과는 janedoering의 항목이 호출됩니다.



Scan 세번째 예제입니다. 위 예제와는 달리, 속성 내에 내재된 속성, 즉 속성 안에 속성 값을 검색할 때 쓰는 조건입니다.

Nested Attributes에 대한 검색 관리도 아래와 같이 할 수 있으며, addresss 속성의 state 속성의 값이 'CA'일 때 나타내는 내용입니다.

response = table.scan(

    FilterExpression=Attr('address.state').eq('CA')

)

items = response['Items']

print(items)

결과는 johndoe와 alicedoe의 항목이 호출됩니다.



Python SDK인 Boto3를 활용하여 DynamoDB를 관리하는 방법에 관한 글은 여기까지입니다.

이 모든 내용은 AWS Boto3 Documentation에 있는 내용이지만, 번역이 되어 있지 않았고,

앞으로도 DynamoDB를 사용할 일이 생길 때 Python으로 어떻게 해야 할 지를 나타내고자 할 때에는 이러한 기본 예제를 들어 활용하면 될 것입니다.


하지만 고급 프로그래밍을 하게 되면 이것보다는 훨씬 복잡한 명령어를 작성해야 할 것입니다.

그렇기 때문에 AWS에서는 이를 위한 예제를 별도로 제공하고 있습니다.

Tic-tac-toe라는 Python Application에서 DynamoDB를 사용한 예제를 AWS에서 제공하고 있으니, 향후 DynamoDB 프로그래밍이 필요할 때에는 위에서 다룬 내용을 바탕으로 하고, 예제 문서를 참고하여 프로그램을 개발하면 될 것으로 생각됩니다.


Tic-tac-toe Python Link: https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/TicTacToe.html


이상 글 마치겠습니다.


 


Comment +0

이번 글에서는 Amazon Web Service(AWS) 에서 DynamoDB를 사용하는 방법을 Python을 이용해서 다루도록 하겠습니다.

처음에 AWS Python 카테고리에서 DynamoDB를 다루고자 했던 것은 아니였지만, 이번 회사에서 기술보고서를 작성하는 과정에 있어서 주제를 DynamoDB를 하다 보니까 블로그에도 같이 다루는 것이 좋을 것 같아서 올려봅니다.


2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #1. 소개

2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #2. 테이블 관리


이번 글은 지난 글에 이어서 AWS SDK for Python인 Boto3 를 사용한 DynamoDB의 항목(Items) 관리에 대해서 다루어보도록 하겠습니다.

모든 내용은 AWS의 Boto3 Documentation에 있는 내용이며, 번역자료가 없기 때문에 제가 직접 실습하면서 나타내도록 하겠습니다.


원본 문서: http://boto3.readthedocs.io/en/latest/guide/


영어 문서이므로 참고하시기 바랍니다.


먼저 항목(Items)이 무엇인지에 대해서 간단히 언급하겠습니다.

항목이란 쉽게 말해서, 데이터 값입니다.

RDBMS에서는 레코드(Record) 또는 행(Row)이라고도 하는데, DynamoDB는 NoSQL의 특성에 맞게 항목(Items)으로 나타납니다.

이 점을 참고하시면 될 것으로 생각됩니다.


이 게시물에 있는 모든 예제는 users Table에서 이루어집니다.

users Table의 기본 키(Primary Key)는 username(Partition Key)과 last_name(Sort Key)로 구성되어 있으니 이 점 반드시 참고 바랍니다.


1. 기본 데이터 처리 - CRUD

DB를 하시는 분은 CRUD가 무엇인지 정도는 다 알 것입니다. 

RDBMS에서는 SQL에서 Insert / Select / Update / Delete의 기능으로도 볼 수 있겠고요.


DynamoDB의 항목 생성/호출/갱신/삭제 또한 마찬가지입니다.


1) 생성

table.put_item(

   Item={

        'username': 'janedoe',

        'first_name': 'Jane',

        'last_name': 'Doe',

        'age': 25,

        'account_type': 'standard_user',

    }

)


생성은 put_item 을 사용하여 입력이 이루어집니다.

위에 언급했다 시피, username과 last_name 속성은 기본 키이므로, first_name, age, account_type은 추가 속성으로 자유롭게 입력된 것을 확인할 수 있습니다.

결과는 다음과 같습니다.


2) 호출

일반적으로 호출이라 함은 SQL에서 select에 해당되는 부분으로 볼 수 있습니다.

하지만 실제 자세한 호출은 아래에서 상세히 다룰 예정이며, 지금 예제는 하나의 값을 단순히 불러오는 예제로 보시면 되겠습니다.

response = table.get_item(

    Key={

        'username': 'janedoe',

        'last_name': 'Doe'

    }

)

item = response['Item']

print(item)

 

위 예제와 같이, 기본 키를 입력해서 해당 키의 값을 불러오는 과정으로, 커맨드 창에서 파이썬을 실행한 결과는 다음과 같습니다.


3) 갱신

갱신은 특정 값을 변경하는 것이므로, 변경 대상 항목과 변경될 값을 입력하면 됩니다.

table.update_item(

    Key={

        'username': 'janedoe',

        'last_name': 'Doe'

    },

    UpdateExpression='SET age = :val1',

    ExpressionAttributeValues={

        ':val1': 26

    }

)

예제에서와 같이, 변경 대상 항목 지정을 위한 Key를 입력하고, UpdateExpression을 통해서 대상 속성의 값을 지정합니다.

그리고 ExpressionAttributeValues를 통해서 특정 값에 대한 변수 값을 입력합니다.

AWS Console에서의 갱신 결과는 아래와 같습니다.


4) 삭제

삭제는 기본 키를 조건으로 지정하면 즉시 삭제가 가능합니다.

table.delete_item(
    Key={
        'username': 'janedoe',
        'last_name': 'Doe'
    }
)

결과는 아래와 같습니다.

AWS Console에서 아무 항목도 없는 것으로 확인될 것입니다.



사실 여기까지는 너무 기본적인 내용입니다.

이제 DynamoDB에서 활용하는 데이터 관리에 대해서 좀 더 알아보도록 하겠습니다.



2. Batch Writing

DynamoDB에서는 대용량의 데이터를 입력할 때, Batch Writing기능을 사용하여 속도를 향상시키고, 요청에 필요할 수를 줄일 수 있습니다. 이 기능은 항목(Item)을 Batch 순서에 의해서 자동으로 조절할 수 있으며, 데이터 전송이 이루어지지 않을 때에 재전송 기능도 수행하도록 되어 있습니다.다.

데이터 추가는 put_item 명령어를 사용하는 것을 기본으로 하며, 반대로 삭제는 delete_item 명령어를 사용하는 것을 기본 명령어로 수행합니다.


라고 제 요량대로 번역해본 것입니다. 원문은 아래와 같습니다.

출처: 맨 위의 Boto3 Documentation


If you are loading a lot of data at a time, you can make use of DynamoDB.Table.batch_writer() so you can both speed up the process and reduce the number of write requests made to the service.

This method returns a handle to a batch writer object that will automatically handle buffering and sending items in batches. In addition, the batch writer will also automatically handle any unprocessed items and resend them as needed. All you need to do is call put_item for any items you want to add, and delete_itemfor any items you want to delete:

 


위의 기본 데이터 처리는 하나의 값을 넣는 형태로 이루어지지만, 대용량으로 한꺼번에 입력이 필요할 때, 이에 대한 속도 처리를 위한 명령어를 Boto3에서 제공한다고 보시면 간단히 이해가 될 것입니다.

일단 Batch Writing을 사용하여 여러 개의 데이터를 입력하는 예제부터 보여드리겠습니다.


with table.batch_writer() as batch:

    batch.put_item(

        Item={

            'account_type': 'standard_user',

            'username': 'johndoe',

            'first_name': 'John',

            'last_name': 'Doe',

            'age': 25,

            'address': {

                'road': '1 Jefferson Street',

                'city': 'Los Angeles',

                'state': 'CA',

                'zipcode': 90001

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'super_user',

            'username': 'janedoering',

            'first_name': 'Jane',

            'last_name': 'Doering',

            'age': 40,

            'address': {

                'road': '2 Washington Avenue',

                'city': 'Seattle',

                'state': 'WA',

                'zipcode': 98109

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'standard_user',

            'username': 'bobsmith',

            'first_name': 'Bob',

            'last_name':  'Smith',

            'age': 18,

            'address': {

                'road': '3 Madison Lane',

                'city': 'Louisville',

                'state': 'KY',

                'zipcode': 40213

            }

        }

    )

    batch.put_item(

        Item={

            'account_type': 'super_user',

            'username': 'alicedoe',

            'first_name': 'Alice',

            'last_name': 'Doe',

            'age': 27,

            'address': {

                'road': '1 Jefferson Street',

                'city': 'Los Angeles',

                'state': 'CA',

                'zipcode': 90001

            }

        }

    )

batch_writer를 사용하여 여러 개의 값을 입력하는 형태입니다.

4개의 값이 순차적으로 입력된 것을 확인할 수 있습니다.


다음은 for 반복문을 이용한 입력 결과입니다.

with table.batch_writer() as batch:

    for i in range(50):

        batch.put_item(

            Item={

                'account_type': 'anonymous',

                'username': 'user' + str(i),

                'first_name': 'unknown',

                'last_name': 'unknown'

            }

        )

순서는 좀 뒤죽박죽인 것 같습니다.


다음은 기본 키를 사용한 예제입니다.

with table.batch_writer(overwrite_by_pkeys=['username', 'last_name']) as batch:

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's1',

            'other': '111',

        }

    )

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's1',

            'other': '222',

        }

    )

    batch.delete_item(

        Key={

            'username': 'p1',

            'last_name': 's2'

        }

    )

    batch.put_item(

        Item={

            'username': 'p1',

            'last_name': 's2',

            'other': '444',

        }

    )

다른 예제와는 다르게, 상단에 overwrite by pkeys = [‘username’,’last_name’] 구문이 들어가 있는 것을 확인할 수 있을 것입니다.

여기에서의 pkeys는 기본키가 들어가며, 파티션 키, 정렬 키의 값이 들어갑니다.


위 예제에서는 [p1, s1, 111], [p1, s1, 222] 값을 입력한 후, [p1, s2] 키 값을 삭제하고 [p1, s2, 444] 값을 입력하는 순서로 되어 있습니다.

하지만 여기서 생각을 해야 할 것이 있습니다.


기본 키가 같을 경우, 세부 속성이 다르더라도 중복된 값이 들어가면 안됩니다.


그러므로 batch.put_item을 일반적으로 썼더라면 에러가 발생할 수 있습니다.

하지만 실제 결과는 다음과 같습니다.

[p1, s1, 222]와 [p1, s2, 444] 2개만 들어간 것을 확인할 수 있습니다.

어떻게 된 것일까요.


이는 batch_writer에서 overwrite by pkeys를 지정했기 때문에 오류가 발생하지 않는 것입니다.

만약에 같은 기본키에 값이 또 들어올 경우에는 overwrite를 해서 먼저 입력된 값을 덮어 씌우라는 뜻이였으므로,

[p1, s1, 111] 의 값이 이미 기본키로 들어가 있었지만, 그 후에 [p1, s1, 222]의 값으로 대체가 된 것으로 보시면 됩니다.


Batch Writer를 통한 입력/삭제는 위와 같이 활용하면 대용량 데이터 입력 시에도 원하는 형태로의 코드 작성이 가능할 것으로 생각됩니다.


다음은 마지막으로 실제 항목, 즉 데이터 호출을 위한 Query & Scan에 대해서 알아보도록 하겠습니다.

Comment +0

이번 글에서는 Amazon Web Service(AWS) 에서 DynamoDB를 사용하는 방법을 Python을 이용해서 다루도록 하겠습니다.

처음에 AWS Python 카테고리에서 DynamoDB를 다루고자 했던 것은 아니였지만, 이번 회사에서 기술보고서를 작성하는 과정에 있어서 주제를 DynamoDB를 하다 보니까 블로그에도 같이 다루는 것이 좋을 것 같아서 올려봅니다.


2018/06/03 - [Onik Lab./AWS Python] - AWS DynamoDB in Python (Boto3) - #1. 소개


이번 글은 Boto3 및 DynamoDB 테이블 관리에 대해서 다루어보도록 하겠습니다.

이전 글에서 언급했다시피, AWS DynamoDB를 사용하기 위해서 Amazon에서는 각 프로그래밍 언어 별 SDK를 배포하고 있다고 하였습니다.

Python SDK도 당연히 있으며, AWS SDK in Python 인 Boto3 를 이용해서 DynamoDB와 연동해보도록 하겠습니다.


원본 문서: http://boto3.readthedocs.io/en/latest/guide/

영어 문서이므로 참고하시기 바랍니다.


1. Boto3 설치

매우 쉽습니다. 이미 Python 2.7 이상 버전이 모두 설치되어 있을 것이므로, pip를 통해서 설치를 하면 됩니다.

$ pip install boto3 


큰 문제가 없다면 설치가 정상적으로 이루어 질 것입니다. 중간 과정은 너무 길어서 생략했습니다.

참고로 중간에 빨간색 에러메시지가 나타날 수 있는데, 해당 부분보다도 성공적으로 설치되었는지 확인만 하면 됩니다. 

(다만 에러메시지 부분은 추후 재확인해보도록 하겠습니다)


2. Table 생성

Boto3 만 설치했는데 테이블을 바로 생성한다고요?

네 그렇습니다. DynamoDB는 AWS의 EC2 Server 구축만 되어있고, Python, Boto3, AWS CLI 설치가 완료되면 곧바로 사용이 가능합니다.


AWS Console 상에서 테이블을 생성하는 것이 가능하지만, Python과의 연동을 위해서 Python을 통해서 생성하도록 하겠습니다.


import boto3

 

# Get the service resource.

dynamodb = boto3.resource('dynamodb')

 

# Create the DynamoDB table.

table = dynamodb.create_table(

    TableName='users',

    KeySchema=[

        {

            'AttributeName': 'username',

            'KeyType': 'HASH'

        },

        {

            'AttributeName': 'last_name',

            'KeyType': 'RANGE'

        }

    ],

    AttributeDefinitions=[

        {

            'AttributeName': 'username',

            'AttributeType': 'S'

        },

        {

            'AttributeName': 'last_name',

            'AttributeType': 'S'

        },

 

    ],

    ProvisionedThroughput={

        'ReadCapacityUnits': 5,

        'WriteCapacityUnits': 5

    }

)

 

# Wait until the table exists.

table.meta.client.get_waiter('table_exists').wait(TableName='users')

 

# Print out some data about the table.

print(table.item_count)


이게 다입니다. 굉장히 쉬울 것입니다.

그리고 실행만 하면 끝.


1) import boto3를 하여 boto3 SDK를 불러옵니다.

2) DynamoDB의 기본 키(Primary Key) 생성을 위해서 Key Schema 속성을 사용하고, 파티션키와 정렬키를 각각 HASH / RANGE 속성값으로 지정합니다.

3) 기본 키에 해당하는 속성의 유형을 AttributeDefinitions로 지정하고, 문자열(String) 유형인 'S"로 지정합니다.

4) 읽기 / 쓰기 용량도 더불어 지정합니다.

5) 커맨드 창에서 Python을 실행하면 '0'이라고 나오는데, 정상입니다. '0'은 생성된 이후 항목(Item) 개수를 나타내는 결과값이기 때문입니다.


생성된 DynamoDB 테이블을 보도록 하겠습니다.


아무 문제 없이 설치가 완료된 것을 볼 수 있습니다.


3. Table 사용

테이블 사용은 매우 간단합니다. 

아래의 세번째 라인의 table 변수에 dynamodb.Table(테이블명)을 입력하면 간단합니다.

import boto3

dynamodb = boto3.resource('dynamodb')

table = dynamodb.Table('users')

단 앞으로 DynamoDB의 Table에서 사용되는 모든 값은 이 table 변수를 통해서 사용하므로, 모든 예제에는 위의 코드가 반드시 들어가야 한다는 점을 참고하시기 바랍니다.


4. Table 삭제

삭제는 위의 table 변수가 지정된 상태에서 delete() 함수를 실행하면 됩니다.

table.delete()


DynamoDB의 Table 생성/사용/삭제 등 관리 방법에 대해서 알아보았습니다.

생각보다는 매우 쉽게 관리가 이루어진다는 것을 알 수 있습니다.

하지만 실제 데이터를 어떻게 관리하는 지도 보아야 되겠죠?


다음 글에서 다루도록 하겠습니다.





Comment +0