> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Shared Group Data

> Use PlayFab Shared Group Data with CloudScript to store turn-based game state, small party data, and manage read/write permissions for group members.

Shared Group Data는 플레이어가 엄격하게 제한된 다른 플레이어 목록과 일부 정보를 공유할 수 있는 간단한 방법입니다.

<Note>
  Shared Group Data는 원래 대부분의 경우 서버 권한 방식으로 동작하도록 설계되었으며, 이전의 권장 사항은 플레이어에게 읽기/쓰기 권한이 부여되어(부정 행위 가능성) 플레이어를 Shared Group Data에 직접 추가하지 *않는* 것이었습니다. 그러나 새로운 [API 액세스 정책](/services/playfab/api-references/api-access-policy)을 통해 원래 설계보다 훨씬 다양한 기능과 보안이 가능해졌습니다. 자세한 내용은 이 문서의 고급 섹션에서 확인할 수 있습니다.
</Note>

<Warning>
  Shared Group Data는 최대 십여 명 이상의 큰 그룹에서는 사용하지 않아야 합니다. 문제 중 하나는 너무 많은 플레이어가 동시에 같은 데이터를 읽으려 하면 데이터 읽기에 지연이 발생한다는 것입니다(Shared Group Data는 Title Data와 같이 많은 플레이어가 동시에 읽도록 설계된 데이터와 달리 *샤딩*되거나 *캐시*되지 않습니다). 또한 플레이어가 서로의 데이터를 덮어쓰는 것을 방지하기 위해 특별한 주의를 기울여야 합니다. 여러 플레이어가 동시에 같은 Key에 쓰려고 하면 그 중 한 쓰기만 “승리”하고, 다른 사용자의 데이터가 손실됩니다.
</Warning>

## 예시: 턴 기반 멀티플레이어 비동기 게임

Shared Group Data의 본래이자 여전히 가장 좋은 사용 사례는 온라인 보드 게임 상태를 저장하는 것으로 가장 잘 설명됩니다. 플레이어들은 명확한 턴 순서에 따라 CloudScript를 통해 데이터를 수정하며 차례를 진행합니다.

플레이어는 로그아웃했다가 나중에 다시 게임을 재개할 수 있으며, 게임 상태는 클라우드에 저장됩니다.

다음 CloudScript 예시는 일반적인 보드 게임에 사용되는 턴 기반 구조입니다. 보드 게임 자체는 의사 코드로 표시되어 있습니다.

### 가정

게임을 나타내는 Shared Group Data가 이미 시작되었고 그 멤버십이 이미 정의되어 있습니다.

```javascript theme={null}
// CloudScript/Javascript
const MY_GAME_GROUP_KEYS: Array<string> = ["gameState", "currentPlayerTurn"];
interface PlayerTurnArgs {
    sharedGroupId: string;
    nextPlayerTurn: string;
    turnData: any;
}
handlers.TakePlayerTurn = function (args: PlayerTurnArgs) {
    var getRequest: PlayFabServerModels.GetSharedGroupDataRequest = { SharedGroupId: args.sharedGroupId, GetMembers: true, Keys: MY_GAME_GROUP_KEYS };
    var gameData: PlayFabServerModels.GetSharedGroupDataResult = server.GetSharedGroupData(getRequest);
    CheckValidPlayer(currentPlayerId, args.sharedGroupId, gameData.Members, gameData.Data["currentPlayerTurn"].Value, args.nextPlayerTurn);
    var newGameStateJson = UpdateGameState(args.turnData, gameData.Data["gameState"].Value);
    var updateRequest: PlayFabServerModels.UpdateSharedGroupDataRequest = {
        SharedGroupId: args.sharedGroupId,
        Data: {
            "gameState": newGameStateJson,
            "currentPlayerTurn": args.nextPlayerTurn
        }
    };
    server.UpdateSharedGroupData(updateRequest);
}
function CheckValidPlayer(playFabId: string, sharedGroupId: string, members: Array<string>, currentPlayerTurn: string, nextPlayerTurn: string): void {
    var validCurPlayer = false;
    var validNextPlayer = false;
    for (var m = 0; m < members.length; m++) {
        if (members[m] === playFabId)
            validCurPlayer = true;
        if (members[m] === nextPlayerTurn)
            validNextPlayer = true;
    }
    if (!validCurPlayer || !validNextPlayer) // Take extreme action against a player trying to cheat
    {
        server.BanUsers({ Bans: [{ PlayFabId: playFabId, Reason: "Trying to play a game you don't belong to: " + sharedGroupId }] });
        throw "You have been banned";
    }

    if (playFabId !== currentPlayerTurn)
        // May wish to additionally implement a spam-counter here and potentially take more extreme action for high-spam count
        throw "Not your turn";
}
function UpdateGameState(turnData: any, currentState: string): string {
    // PSEUDO-CODE-STUB: Update the turn-based game state according to the rules of this game
    return JSON.stringify({});
}
```

전반적으로, 위에서 언급했듯이 그룹 크기가 상대적으로 작은 한 Shared Group Data를 사용하여 파티/레이드 또는 기타 준영구적인 플레이어 그룹을 구현할 수 있습니다.

현재 엄격하게 강제되는 제한은 없지만, 다수의 플레이어를 대상으로 하는 사용은 지원되지 않으며, 극단적인 경우 다른 서비스 사용자에게 영향을 주지 않기 위해 타이틀 기능이 제한(스로틀링)될 수 있습니다.

### 주요 제한 사항

* **Shared Group Data**:
  * 단순한 Key/Value Pair 데이터(문자열)만 포함합니다. 인벤토리 아이템, Statistics, Virtual Currency 등 다른 데이터 형식으로 사용하려면 타이틀이 필요한 변환을 제공해야 합니다.
  * *샤딩*되지도 *캐시*되지도 않으므로 여러 플레이어가 동시에 접근할 때 응답성이 좋지 않습니다. 이 기능을 사용하는 기능은 소규모 플레이어 그룹을 염두에 두고 설계해야 하며 동시 쓰기를 허용해서는 안 됩니다.

### 클라이언트 권한 관련 고려 사항

그룹 내에 역할/등급 시스템이 없으므로, 그룹의 모든 멤버는 그룹 내에서 절대적인 권한을 갖습니다(정의된 리더가 없습니다).

솔직히 말해, 이는 [API 액세스 정책](/services/playfab/api-references/api-access-policy)으로 클라이언트 Shared Group Data 메서드를 비활성화하지 않는 한, 클라이언트가 *데이터를 완전히 제어*하게 되어 데이터가 악용될 수 있음을 의미합니다.

가장 좋은 방법은 게임 플레이에 영향을 미치는 데이터에는 Shared Group Data를 *사용하지 않거나*, 클라이언트 API에서 Shared Group Data 메서드를 비활성화하는 것입니다.


## Related topics

- [Profile Writes 미터 API 설명](/ko/services/playfab/pricing/meters/profile-writes.md)
- [Entity Groups](/ko/services/playfab/community/associations/groups/quickstart.md)
- [XR-052 사용자 상태, 타이틀 저장 위치, 로밍](/ko/publishing/certification/xr/xr-052.md)
- [PC 및 모바일 게임용 XBOX Requirement 테스트 케이스](/ko/publishing/certification/pc-policy-tests.md)
- [PlayFab 릴리스 노트 2015](/ko/services/playfab/release-notes/2015.md)
