DynamoDB의 게임 프로필 스키마 설계
게임 프로필 비즈니스 사용 사례
이 사용 사례에서는 DynamoDB를 사용하여 게임 시스템을 위한 플레이어 프로필을 저장하는 방법을 설명합니다. 사용자(이 경우 플레이어)는 많은 최신 게임, 특히 온라인 게임을 이용하기 전에 프로필을 생성해야 합니다. 게임 프로필에는 일반적으로 다음이 포함됩니다.
-
사용자 이름과 같은 기본 정보
-
아이템 및 장비와 같은 게임 데이터
-
태스크 및 활동과 같은 게임 레코드
-
친구 목록과 같은 소셜 정보
이 애플리케이션의 세분화된 데이터 쿼리 액세스 요구 사항을 충족하기 위해 프라이머리 키(파티션 키 및 정렬 키)는 일반 이름(PK 및 SK)을 사용하므로 아래에서 볼 수 있듯이 다양한 유형의 값으로 오버로드될 수 있습니다.
이 스키마 설계의 액세스 패턴은 다음과 같습니다.
-
사용자의 친구 목록 가져오기
-
플레이어의 모든 정보 가져오기
-
사용자의 아이템 목록 가져오기
-
사용자의 아이템 목록에서 특정 아이템 가져오기
-
사용자 캐릭터 업데이트
-
사용자의 아이템 개수 업데이트
게임 프로필의 크기는 게임마다 다릅니다. 큰 속성 값 압축을 통해 DynamoDB의 항목 제한에 맞출 수 있고, 비용을 절감할 수 있습니다. 처리량 관리 전략은 플레이어 수, 초당 플레이한 게임 수, 워크로드의 계절성 같은 다양한 요인에 따라 달라집니다. 일반적으로 새로 출시되는 게임의 경우, 플레이어 수와 인기도를 알 수 없으므로 온디맨드 처리량 모드로 시작하겠습니다.
게임 프로필 엔터티 관계 다이어그램
다음은 게임 프로필 스키마 설계에 사용할 엔터티 관계 다이어그램(ERD)입니다.
![사용자, 게임, 점수와 같은 엔터티 간의 관계를 보여주는 게임 프로필의 ER 다이어그램.](images/DataModeling/GamingProfileERD.png)
게임 프로필 액세스 패턴
다음은 소셜 네트워크 스키마 설계 시 고려할 액세스 패턴입니다.
-
getPlayerFriends
-
getPlayerAllProfile
-
getPlayerAllItems
-
getPlayerSpecificItem
-
updateCharacterAttributes
-
updateItemCount
게임 프로필 스키마 설계 진화
위의 ERD에서 이것이 데이터 모델링의 일대다 관계 유형임을 알 수 있습니다. DynamoDB에서는 일대다 데이터 모델을 항목 컬렉션으로 구성할 수 있는데, 이는 외래 키를 통해 여러 테이블을 생성하고 연결하는 기존 관계형 데이터베이스와는 다릅니다. 항목 컬렉션은 동일한 파티션 키 값을 공유하지만 정렬 키 값이 다른 항목의 그룹입니다. 항목 컬렉션 내에서 각 항목은 다른 항목과 구분되는 고유한 정렬 키 값을 갖습니다. 이 점을 염두에 두고 각 엔터티 유형별로 HASH
값과 RANGE
값에 다음과 같은 패턴을 사용해 보겠습니다.
우선, 모델을 향후에도 사용할 수 있도록 PK
및 SK
같은 일반 이름으로 다양한 유형의 엔터티를 동일한 테이블에 저장합니다. 가독성을 높이기 위해 데이터 유형을 나타내는 접두사를 포함하거나 Entity_type
또는 Type
이라는 임의의 속성을 포함할 수 있습니다. 현재 예제에서는 player
로 시작하는 문자열을 사용하여 player_ID
를 PK
로 저장하고, entity name#
를 SK
의 접두사로 사용하고, 이 데이터가 어떤 엔터티 유형인지 나타내는 Type
속성을 추가합니다. 이를 통해 향후 더 많은 엔터티 유형을 저장할 수 있고, GSI Overloading 및 Sparse GSI 같은 고급 기술을 사용하여 더 많은 액세스 패턴을 충족할 수 있습니다.
액세스 패턴 구현을 시작해 보겠습니다. 플레이어 추가와 장비 추가 같은 액세스 패턴은 PutItem
작업을 통해 구현할 수 있으므로 무시해도 됩니다. 이 문서에서는 위에 나열된 일반적인 액세스 패턴에 초점을 맞추겠습니다.
1단계: 액세스 패턴 1(getPlayerFriends
) 처리
이 단계로 액세스 패턴 1(getPlayerFriends
)을 처리합니다. 현재 설계에서는 우정이 단순하고 게임 내 친구 수가 적습니다. 간단히 하기 위해 목록 데이터 유형을 사용하여 친구 목록을 저장합니다(1:1 모델링). 이 설계에서는 GetItem
을 사용하여 이 액세스 패턴을 충족합니다. GetItem
작업에서는 특정 항목을 가져오기 위해 파티션 키 및 정렬 키 값을 명시적으로 제공합니다.
하지만 게임에 많은 수의 친구가 있고 친구 간의 관계가 복잡한 경우(예: 친구 관계가 초대 구성 요소와 수락 구성 요소가 모두 있는 양방향 우정), 친구 목록 크기를 무제한 확장하려면 다대다 관계를 사용하여 각 친구를 개별적으로 저장해야 합니다. 또한 우정을 변경하려면 여러 항목에서 동시에 작업해야 하는 경우, DynamoDB 트랜잭션을 사용하여 여러 작업을 그룹화하여 단일한 전부 아니면 전무 방식 TransactWriteItems
또는 TransactGetItems
작업으로 제출할 수 있습니다.
![Friends 엔터티의 게임 프로필에 대한 복잡한 다대다 관계 다이어그램.](images/DataModeling/GamingProfile1.png)
2단계: 액세스 패턴 2(getPlayerAllProfile
), 3(getPlayerAllItems
), 4(getPlayerSpecificItem
) 처리
이 단계를 사용하여 액세스 패턴 2(getPlayerAllProfile
), 3(getPlayerAllItems
), 4(getPlayerSpecificItem
)를 처리합니다. 이 세 가지 액세스 패턴에 공통적으로 있는 것은 Query 작업을 사용하는 범위 쿼리입니다. 쿼리 범위에 따라 실제 개발에서 일반적으로 사용되는 키 조건 및 필터 식이 사용됩니다.
쿼리 작업에서는 파티션 키에 단일 값을 제공하고 해당 파티션 키 값을 가진 모든 항목을 가져옵니다. 액세스 패턴 2(getPlayerAllProfile
)는 이 방식으로 구현됩니다. 원하는 경우, 테이블에서 읽을 항목을 결정하는 문자열인 정렬 키 조건식을 추가할 수 있습니다. 액세스 패턴 3(getPlayerAllItems
)은 ITEMS#
로 시작하는 정렬 키의 키 조건을 추가하여 구현됩니다. 또한 애플리케이션 측 개발을 단순화하기 위해 필터 식을 사용하여 액세스 패턴 4(getPlayerSpecificItem
)를 구현할 수 있습니다.
다음은 Weapon
카테고리의 항목을 필터링하는 필터 식을 사용하는 의사 코드 예제입니다.
filterExpression: "ItemType = :itemType" expressionAttributeValues: {":itemType": "Weapon"}
![다양한 액세스 패턴을 구현하도록 파티션 키 및 정렬 키 조건을 포함한 쿼리 작업 사용.](images/DataModeling/GamingProfile2.png)
참고
필터 식은 쿼리가 완료된 후 결과가 클라이언트에 반환되기 전에 적용됩니다. 따라서 쿼리는 필터 식이 있는지 여부에 상관없이 동일한 양의 읽기 용량을 사용합니다.
액세스 패턴이 대규모 데이터 세트를 쿼리하고 대량의 데이터를 필터링하여 작은 데이터 하위 집합만 유지하는 것이라면 DynamoDB 파티션 키와 정렬 키를 보다 효과적으로 설계하는 것이 적절한 접근 방식입니다. 예를 들어 특정 ItemType
을 얻는 위의 예제에서 각 플레이어마다 항목이 많고 특정 ItemType
을 쿼리하는 것이 일반적인 액세스 패턴이라면 ItemType
을 복합 키로 SK
에 가져오는 것이 더 효율적입니다. 데이터 모델은 다음과 같습니다. ITEMS#ItemType#ItemId
3단계: 액세스 패턴 5(updateCharacterAttributes
) 및 6(updateItemCount
) 처리
이 단계를 사용하여 액세스 패턴 5(updateCharacterAttributes
)와 6(updateItemCount
)을 처리합니다. 플레이어가 화폐를 줄이거나 아이템 중 특정 무기 수량을 수정하는 등 캐릭터를 수정해야 할 경우, UpdateItem
을 사용하여 이러한 액세스 패턴을 구현합니다. 플레이어의 화폐를 업데이트하되 최소 금액 이하로 내려가지 않도록 하기 위해 최소 금액 이상일 경우에만 잔액을 줄일 수 있는 조건 표현식을 추가할 수 있습니다. 다음은 의사 코드 예제입니다.
UpdateExpression: "SET currency = currency - :amount" ConditionExpression: "currency >= :minAmount"
![설정된 금액 미만이 되지 않도록 플레이어의 통화를 수정하기 위해 조건 표현식과 함께 UpdateItem 사용.](images/DataModeling/GamingProfile4-Update-player-Currency.png)
DynamoDB로 개발하고 Atomic Counters를 사용하여 인벤토리를 줄이는 경우, 낙관적 잠금을 사용하여 멱등성을 보장할 수 있습니다. 다음은 Atomic Counters의 의사 코드 예제입니다.
UpdateExpression: "SET ItemCount = ItemCount - :incr" expression-attribute-values: '{":incr":{"N":"1"}}'
![ItemCount 속성 값을 5에서 4로 줄이도록 원자성 카운터 사용.](images/DataModeling/GamingProfile5-Update-Item-Count.png)
또한 플레이어가 화폐로 아이템을 구매하는 시나리오에서는 전체 프로세스가 통화를 차감하는 동시에 아이템을 추가해야 합니다. DynamoDB Transactions를 사용하여 여러 작업을 그룹화하고 이를 하나의 전부 아니면 전무 TransactWriteItems
또는 TransactGetItems
작업으로 제출할 수 있습니다. TransactWriteItems
는 하나의 전부 아니면 전무 작업에서 최대 100개의 쓰기 작업을 그룹화하는 동기식 및 멱등성 쓰기 작업입니다. 작업은 원자 단위로 완료되므로 작업이 모두 성공하거나 모두 실패하게 됩니다. 트랜잭션은 화폐 중복 또는 소멸의 위험을 없애는 데 도움이 됩니다. 트랜잭션에 대한 자세한 내용은 DynamoDB Transactions 예 섹션을 참조세요.
모든 액세스 패턴과 스키마 설계에서 이를 처리하는 방법이 아래 표에 요약되어 있습니다.
액세스 패턴 | 기본 테이블/GSI/LSI | Operation | 파티션 키 값 | 정렬 키 값 | 기타 조건/필터 |
---|---|---|---|---|---|
getPlayerFriends | 기본 테이블 | GetItem | PK=PlayerID | SK=“FRIENDS#playerID” | |
getPlayerAllProfile | 기본 테이블 | 쿼리 | PK=PlayerID | ||
getPlayerAllItems | 기본 테이블 | 쿼리 | PK=PlayerID | SK begins_with “ITEMS#” | |
getPlayerSpecificItem | 기본 테이블 | 쿼리 | PK=PlayerID | SK begins_with “ITEMS#” | filterExpression: "ItemType = :itemType" expressionAttributeValues: { ":itemType": "Weapon" } |
updateCharacterAttributes | 기본 테이블 | UpdateItem | PK=PlayerID | SK=“#METADATA#playerID” | UpdateExpression: "SET currency = currency - :amount" ConditionExpression: "currency >= :minAmount" |
updateItemCount | 기본 테이블 | UpdateItem | PK=PlayerID | SK =“ITEMS#ItemID” | update-expression: "SET ItemCount = ItemCount - :incr" expression-attribute-values: '{":incr":{"N":"1"}}' |
게임 프로필 최종 스키마
다음은 최종 스키마 설계입니다. 이 스키마 설계를 JSON 파일로 다운로드하려면 GitHub의 DynamoDB 예제
기본 테이블:
![이전 액세스 패턴 구현의 결과를 포함하는 테이블의 최종 스키마 설계.](images/DataModeling/GamingProfile6-FinalSchema.png)
이 스키마 설계와 함께 NoSQL Workbench 사용
이 최종 스키마를 DynamoDB 데이터 모델링, 데이터 시각화, 쿼리 개발 기능을 제공하는 시각적 도구인 NoSQL Workbench로 가져와서 새 프로젝트를 추가로 탐색하고 편집할 수 있습니다. 시작하려면 다음 단계를 따릅니다.
-
NoSQL Workbench 다운로드 자세한 내용은 DynamoDB용 NoSQL Workbench 다운로드 단원을 참조하십시오.
-
위에 나열된 JSON 스키마 파일을 다운로드합니다. 이 파일은 이미 NoSQL Workbench 모델 형식으로 되어 있습니다.
-
JSON 스키마 파일을 NoSQL Workbench로 가져옵니다. 자세한 내용은 기존 데이터 모델 가져오기 단원을 참조하십시오.
-
NOSQL Workbench로 가져온 후 데이터 모델을 편집할 수 있습니다. 자세한 내용은 기존 데이터 모델 편집 단원을 참조하십시오.
-
데이터 모델을 시각화하거나, 샘플 데이터를 추가하거나, CSV 파일에서 샘플 데이터를 가져오려면 NoSQL Workbench의 Data Visualizer 기능을 사용하세요.