다음을 통해 공유


공유 그룹 데이터 사용

공유 그룹 데이터를 사용하면 플레이어가 제한된 다른 플레이어 목록과 함께 일부 정보를 쉽게 공유할 수 있습니다.

참고 항목

공유 그룹 데이터는 원래 서버에서 구동되도록 디자인되었습니다. 대부분의 경우에 신뢰할 수 있는 방식이었고, 이전에는 읽기/쓰기 권한(부정 행위에 악용될 수 있는)이 부여되기 때문에 공유 그룹 데이터에 플레이어를 직접 추가하지 ‘않는 것’이 좋다고 여겨졌습니다. 하지만 새로운 API 액세스 정책은 기능 및 보안 면에서 원래 디자인보다 훨씬 더 다양해졌습니다. 자세한 내용은 이 문서의 고급 섹션을 참조하세요.

Warning

공유 그룹 데이터는 플레이어 수가 열댓 명을 넘는 큰 그룹에서는 사용하지 않아야 합니다. 한 가지 문제는 너무 많은 플레이어가 동일한 데이터를 동시에 읽으려고 시도하면 데이터를 읽을 때 지연이 발생한다는 점입니다. 공유 그룹 데이터는 타이틀 데이터와 같이 여러 플레이어가 한 번에 읽을 수 있도록 지원되는 방식인 ‘분할’ 또는 ‘캐시’ 방식을 따르지 않습니다. 그리고 플레이어가 각각 다른 플레이어의 데이터를 겹쳐쓰지 못하도록 방지하는 특별한 주의가 필요합니다. 여러 플레이어가 동일한 키를 동시에 쓰려고 시도할 때, 이러한 쓰기 시도 중 하나만 “성공”하게 되고, 결국 다른 사용자의 데이터는 모두 손실됩니다.

예: 턴 기반의 멀티 플레이 비동기 게임

공유 그룹 데이터에 원래부터 사용되었지만, 여전히 가장 좋은 사용 사례는 온라인 보드 게임의 상태를 저장하는 방식으로 설명하는 것이 가장 좋습니다. 플레이어들은 명확한 순서에 따라 CloudScript를 통해 데이터를 차례로 수정합니다.

플레이어는 로그오프하고 나중에 플레이를 재개할 수 있으며, 이 경우 해당 게임 상태가 클라우드에 저장됩니다.

다음 CloudScript 예는 모든 일반적인 보드 게임에 사용되는 턴 기반 구조입니다. 보드 게임 자체는 의사 코드로 스텁됩니다.

가정

게임을 나타내는 공유 그룹 데이터가 이미 시작되었고, 해당 멤버십이 이미 정의되어 있습니다.

// 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({});
}

상위 수준에서 볼 때, 그룹 크기가 앞에서 설명한 것처럼 비교적 작을 때는 공유 그룹 데이터를 사용하여 파티/레이드 또는 플레이어의 다른 반영구 그룹을 구현할 수 있습니다.

현재까지 엄격하게 적용되는 제한은 없지만, 많은 플레이어가 포함된 사용은 지원되지 않으며, 극한의 경우, 서비스에 포함된 다른 사용자에 대한 영향을 방지하기 위해 타이틀 기능이 제한될 수 있습니다.

주요 제한 사항

  • 공유 그룹 데이터:
    • 단순한 키/값 쌍 데이터만 포함합니다(문자열). 인벤토리 아이템, 통계, 가상 통화 등의 다른 데이터 유형에 사용하기 위해서는 타이틀에서 필요한 변환을 제공해야 합니다.
    • 분할되거나 캐시되지도 않으므로, 여러 플레이어가 동시에 액세스하면 응답하지 않게 됩니다. 이를 사용할 때는 소규모 플레이어 그룹을 염두에 두고 디자인해야 하며, 동시 쓰기를 허용하지 않아야 합니다.

클라이언트 권한 문제

그룹 내에는 역할/순위 시스템이 없습니다. 즉, 그룹 내 어떤 멤버라도 해당 그룹 내에서 절대 권한을 갖습니다(정의된 리더가 없음).

직설적으로 말하면, 따라서 API 액세스 정책으로 클라이언트 공유 그룹 데이터 메서드를 비활성화하지 않는 한, 클라이언트가 ‘데이터에 대해 완전한 제어 권한’을 가지며, 그 결과 데이터가 악용될 수 있습니다.

최상의 방법은 게임 플레이에 영향을 주는 데이터에 대해서는 공유 그룹 데이터를 사용하지 ‘않거나’, 클라이언트 API에서 공유 그룹 데이터 메서드를 비활성화하는 것입니다.