> ## 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.

# 게임 저장 워크스루 및 샘플

> 게임 저장 워크스루 및 샘플

이 문서에서는 게임 저장(Game Saves)을 사용할 때 자주 접하는 개발 및 마이그레이션 시나리오에 대한 단계별 안내를 제공합니다. Microsoft Partner Center에서 필요한 필수 설정, 데이터를 안전하게 쓰기 위한 모범 사례, 플랫폼별 저장 관리, 권장 테스트 절차를 다룹니다.

## Partner Center 구성

### 타이틀에 대해 XBOX 서비스 및 게임 저장 활성화

게임 저장 API를 사용하려면 Partner Center에서 다음 단계를 완료하세요.

* XBOX 서비스를 활성화합니다.
  1. [Partner Center](https://partner.microsoft.com/dashboard/home)에 로그인합니다.
  2. 타이틀로 이동한 다음, 설정에서 XBOX 서비스를 활성화합니다. 이 단계에 대한 자세한 내용은 [Managed Partners를 위한 Partner Center에서 앱 또는 게임 설정하기](/services/xbox-services/fundamentals/portal-config/live-setup-partner-center-partners#2-contact-your-microsoft-representative-to-enable-your-app-or-game)를 참조하세요.
* 서비스 구성 식별자(SCID)를 가져옵니다. 모든 읽기 및 쓰기 작업은 SCID와 연결되어야 합니다. SCID는 게임 저장 초기화에도 사용됩니다.
  * Partner Center에서 타이틀의 **XBOX services** > **XBOX settings** 탭에서 SCID를 확인할 수 있습니다. 이 페이지에서 Microsoft 계정(MSA) App ID(MSAAppID)도 확인할 수 있습니다.
    <img src="https://mintcdn.com/microsoft-4404708b/UZTRJSf0emX1fheE/images/gdk/features/common/partner-center-xbox-services-view.png?fit=max&auto=format&n=UZTRJSf0emX1fheE&q=85&s=7ba30f0150039b4e968e6915ad0eb4dd" alt="Partner Center XBOX services 보기." width="622" height="293" data-path="images/gdk/features/common/partner-center-xbox-services-view.png" />

SCID와 MSAAppID를 확보한 후에는 이 App ID를 타이틀의 구성(.mgc) 파일에 추가합니다.

게임 구성 파일에 대한 자세한 내용은 [Microsoft Game Config .mgc 만들기](/build/core-features/common/game-config/MicrosoftGameConfig-Overview)를 참조하세요.

## 개발 시나리오

### 게임 저장을 코드의 어디에 통합해야 하나요?

게임 저장 로직은 사용자 로그인에 의존합니다. 게임 저장 코드는 사용자 로그인 흐름 옆에 추가하세요.

### 게임 저장 데이터가 손상되지 않도록 하려면 어떻게 해야 하나요?

데이터를 안전하게 저장하고 손상을 방지하려면 다음 단계를 따르세요. 이 지침은 모든 저장 작업에 적용됩니다.

1. 임시 파일에 씁니다.
   * 현재 저장 파일을 덮어쓰는 대신, 저장 데이터를 새 파일(예: `save.tmp`)로 직렬화합니다. 이 단계는 쓰기 도중에 프로세스가 중단되더라도 기존 저장 파일을 보호합니다.
2. 쓰기가 디스크에 완전히 커밋된 후 쓰기 핸들을 닫습니다.
3. Win32 [ReplaceFile](https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-replacefilea)을 사용하여 기존 저장 파일을 새 임시 파일로 원자적으로 교체합니다.

### 오프라인 장치는 어떻게 지원하나요?

게임 저장을 초기화하기 전과 후 모두에서 연결이 끊긴 경우 타이틀이 어떻게 동작해야 하는지 결정하는 것은 개발자의 책임입니다.

오프라인 동작에 대한 자세한 내용은 [게임 저장 동기화 흐름 이해하기](/build/core-features/common/game-save/game-saves-syncing#connection-check)를 참조하세요.

### 어떤 사용자 상호작용을 알고 있어야 하나요?

작업에 사용자 입력이 필요한 경우 OS가 시스템 프롬프트를 표시합니다. 이러한 프롬프트에 대한 자세한 내용은 [게임 저장 대화 상자](/build/core-features/common/game-save/game-saves-dialogues)를 참조하세요.

### 로컬 및 장치에만 저장하는 방법이 있나요?

게임 저장 초기화 프로세스에 `null` 사용자 핸들을 전달하면 시스템은 장치 전용 공급자를 생성합니다. 데이터는 로컬에 저장되며 장치에 유지되고, 최대 256MB까지 저장할 수 있습니다. 데이터는 클라우드와 동기화되지 않습니다.

게임 저장 스토리지에 대한 자세한 내용은 [게임 저장 스토리지 시스템](/build/core-features/common/game-save/game-saves-storage-systems)을 참조하세요.

### 장치를 통한 게임 저장 관리

#### 파일 탐색기를 사용하여 PC에서 로컬 게임 저장에 액세스하기

타이틀이 PC에서 실행되는 경우 파일에 직접 액세스할 수 있습니다. 게임 저장 API 구현에 따라 다음 위치에서 로컬 게임 저장에 액세스할 수 있습니다.

| 게임 저장 API      | 파일 경로                                                                         |
| :------------- | :---------------------------------------------------------------------------- |
| XGameSaveFiles | `%AppData%\Local\Packages\<PACKAGE_NAME>\SystemAppData\xgs\<HexXuid>_<Scid>\` |
| XGameSave      | `%AppData%\Local\Packages\<PACKAGE_NAME>\SystemAppData\wgs\<HexXuid>_<Scid>\` |

PC에서 데이터를 조작할 때에도 동기화 로직은 계속 적용됩니다. 예를 들어, 타이틀이 잠금을 갖고 있지 않은 상태에서 데이터를 수정하면 충돌이 발생합니다.

#### 콘솔에서 로컬 게임 저장에 액세스하기

XBOX UI를 통해 콘솔 저장 데이터를 관리합니다. 다음 단계를 사용하여 액세스합니다.

1. XBOX 컨트롤러의 **홈** 버튼을 선택합니다.
2. **내 게임 및 앱** > **모두 보기**를 선택합니다.
3. 게임 위에 커서를 놓고 **보기** 버튼을 선택합니다.
4. **저장된 데이터**를 선택합니다.

<img src="https://mintcdn.com/microsoft-4404708b/sIrPFR_ir_sNKVEv/images/gdk/features/common/console-storage-management.png?fit=max&auto=format&n=sIrPFR_ir_sNKVEv&q=85&s=1440050534d3c4d168d1e964d3638afe" alt="콘솔 스토리지 게임 저장 관리 보기." width="1314" height="377" data-path="images/gdk/features/common/console-storage-management.png" />

콘솔에서 직접 데이터를 조작할 때에는 다음 사항을 고려하세요.

* 시스템 UI를 사용하여 콘솔에서 데이터를 삭제해도 클라우드에 저장된 사본은 제거되지 않습니다. 타이틀을 다시 실행하면 클라우드에서 데이터를 동기화합니다.
* 장치 전용 공급자 데이터는 이름이 없는 사용자로 표시됩니다. 이 데이터는 장치에 유지되며, 클라우드와 동기화되지 않고 장치에 종속됩니다.

장치 전용 공급자에 대한 자세한 내용은 [게임 저장 스토리지 시스템](/build/core-features/common/game-save/game-saves-storage-systems#game-saves-storage-systems)을 참조하세요.

게임 저장을 더 세밀하게 제어하려면 [게임 저장 도구](/build/core-features/common/game-save/game-saves-tools#manipulating-game-saves)를 사용하세요.

## 테스트 시나리오

테스트 케이스를 만들 때 데이터 유효성 검사를 게임 저장 로직과 분리하세요.

### 게임 저장이 클라우드와 올바르게 동기화되는지 테스트하기

올바른 동기화를 테스트하려면 다음 단계를 사용하세요. 테스트 흐름은 동작을 검증합니다.

`XGameSaveFiles`:

1. SCID가 올바른지 확인합니다.
2. 올바른 사용자 핸들을 사용하고 있는지 확인합니다.
3. 타이틀이 현재 게임 세션 동안 `XGameSaveFilesGetFolderWithUIAsync`를 호출하는지 확인합니다. 타이틀이 일시 중단 상태에서 재개되는 경우에는 이 함수를 호출합니다.
   1. Fiddler를 사용하여 잠금이 획득되었는지 확인합니다.
   2. 이 경로를 저장하고, 나중에 데이터가 업로드되고 있는지 확인하는 데 사용합니다.
4. `XGameSaveFilesGetFolderWithUIAsync`가 제공한 파일 경로에 일부 데이터를 씁니다.
5. 타이틀을 종료하거나 일시 중단합니다.
6. OS가 자동으로 클라우드에 데이터를 업로드하고 잠금을 해제할 때까지 10\~30초 정도 기다립니다.
   1. Fiddler를 사용하여 데이터가 업로드되고 잠금이 해제되었는지 확인합니다.
7. `XGameSaveFilesGetFolderWithUIAsync`가 제공한 폴더 내의 데이터를 수동으로 삭제합니다.
   1. 콘솔에서는 플레이어 설정을 통해 이 데이터에 액세스합니다.
8. 타이틀을 다시 실행한 후 사용자를 로그인시키려고 시도합니다.
9. 동기화 대화 상자가 나타나 클라우드에서의 활성 다운로드 동기화를 표시합니다.

동기화가 성공했는지 테스트하는 데 도움이 되는 다음 리소스를 참조하세요.

* [트래픽을 검사하고 저장을 조작하기 위한 게임 저장 도구](/build/core-features/common/game-save/game-saves-tools)
* [게임 저장 동기화 흐름 이해하기](/build/core-features/common/game-save/game-saves-syncing)

### 게임 저장이 올바르게 로밍되는지 테스트하기

데이터가 로밍되는지 확인하는 테스트 계획은 [XR-052-06 테스트 계획](https://learn.microsoft.com/build/store/policies/XR/XR052#052-06-cloud-storage-roaming)을 참조하세요.

## 마이그레이션 시나리오

### 타이틀 간에 게임 저장 공유하기

한 타이틀의 데이터를 다른 타이틀로 전송하거나 액세스하려면 두 단계를 완료하세요.

1. Partner Center에서 액세스하려는 타이틀의 액세스 정책을 수정합니다.
2. 소스 코드에서 두 타이틀 모두에 대해 게임 저장 공급자를 초기화합니다.

#### 액세스 정책 수정하기

타이틀은 액세스 정책을 구성하여 어떤 타이틀이 자신의 게임 저장 데이터에 액세스할 수 있는지 제어합니다.

1. [Partner Center](https://partner.microsoft.com/dashboard)로 이동합니다.
2. **Apps and games** > **\<your title>** > **Gameplay settings**를 선택합니다.
3. **Gameplay Settings**에서 **Access Policies**를 선택한 다음, **Connected Storage**를 펼칩니다.
4. **Add app/service**를 선택한 다음, 액세스를 제공할 타이틀을 추가합니다.
5. 타이틀 추가를 마쳤으면 **Save**를 선택한 다음, **Publish**를 선택합니다. 변경 사항은 한 시간 이내에 적용됩니다.

다음 스크린샷은 GameSaveFilesCombo 타이틀을 GameSaveSample 타이틀에서 완전히 액세스할 수 있도록 설정하는 예를 보여줍니다.

<img src="https://mintcdn.com/microsoft-4404708b/UZTRJSf0emX1fheE/images/gdk/features/common/partner-center-access-policy.png?fit=max&auto=format&n=UZTRJSf0emX1fheE&q=85&s=25eae43c7e7d88b824558596d849cbfa" alt="타이틀의 액세스 정책을 수정하는 Partner Center 보기." width="1280" height="598" data-path="images/gdk/features/common/partner-center-access-policy.png" />

#### 게임 저장 공급자 초기화하기

이제 첫 번째 타이틀에 액세스할 권한이 있으므로, 다른 타이틀에서 `XGameSave` 데이터를 읽을 수 있습니다.

* `XGameSave`를 사용하는 경우, 각 타이틀에 대해 `XGameSaveInitializeProvider` 또는 `XGameSaveInitializeProviderAsync`를 호출합니다.
* `XGameSaveFiles`를 사용하는 경우, 공급자는 암묵적으로 초기화됩니다. 각 타이틀에 대해 `XGameSaveFilesGetFolderWithUiAsync`를 호출합니다.

### XGameSave와 XGameSaveFiles 간의 상호 운용성

타이틀에서 `XGameSave`와 `XGameSaveFiles`를 함께 사용해야 할 수도 있습니다. 일반적인 이유는 다음과 같습니다.

* 게시자가 이미 `XGameSave`를 사용하는 콘솔용 기존 타이틀을 보유하고 있는 경우.
* 게시자가 그 기존 타이틀을 `XGameSaveFiles`를 사용하도록 업데이트하고 싶지 않은 경우.
* 게시자가 PC 타이틀에 `XGameSaveFiles`를 추가하는 것이 `XGameSave`를 사용하는 것보다 쉽다고 판단하지만, 여전히 PC, 콘솔, XBOX 게임 스트리밍 간의 크로스 저장을 지원하고자 하는 경우.

`XGameSave`와 `XGameSaveFiles` 간의 이동은 비교적 간단합니다. 타이틀이 [XGameSaveFilesGetFolderWithUiAsync](/reference/system/xgamesavefiles/functions/xgamesavefilesgetfolderwithuiasync)를 호출하면, 다음 규칙을 사용하여 컨테이너와 블롭을 디렉터리와 파일에 매핑합니다.

* 컨테이너 이름의 슬래시(/)는 파일이 위치할 디렉터리 구조를 생성합니다.
* 다음 문자는 `XGameSaveFiles`에서 유효하지 않습니다. 시스템이 이러한 문자를 만나면 밑줄(\_)로 매핑합니다.
  * \0에서 \001f까지의 문자(포함).
* 다음 문자는 `XGameSaveFiles`에서 유효하지 않습니다. 시스템이 이러한 문자를 만나면 마침표(.)로 매핑합니다.
  * 따옴표(")
  * 보다 작음 기호(\<)
  * 보다 큼 기호(>)
  * 파이프(|)
  * 별표(\*)
  * 물음표(?)
  * 백슬래시(\\)
* 블롭 이름의 슬래시(/)는 파일 이름의 마침표(.)로 매핑됩니다.
* 파일은 16MB로 제한됩니다. `XGameSave`는 최대 16MB의 업로드 크기를 지원합니다.

타이틀이 `XGameSaveFiles`에서 다시 `XGameSave`로 이동할 때, 파일 이름이 변경되지 않았거나 이동되지 않은 경우 원래의 컨테이너 및 블롭 이름이 복원됩니다.

### 코드 없는 클라우드 저장을 사용하여 이전 타이틀을 PC 게임 저장으로 이식하기

PC Game Pass로 이식하는 일부 타이틀은 코드 없는 클라우드 저장 솔루션이 필요할 수 있습니다. 이러한 요구 사항은 다음 시나리오에서 발생할 수 있습니다.

* 타이틀이 x86 애플리케이션으로 실행되는 경우. 이 경우 패키지 형태로만 Microsoft Game Development Kit(GDK)를 사용합니다.
* Unreal Engine의 Blueprint나 Unity의 Bolt와 같은 도구를 사용하여 사용자 지정 코드 없이 타이틀이 만들어진 경우.

코드 없는 클라우드 저장을 사용하는 타이틀은 표준 Win32 파일 I/O API를 통해 지정된 저장 디렉터리에서 읽고 씁니다. 시스템이 데이터를 자동으로 동기화합니다. 동기화 및 업로드를 처리하기 위해 특별한 코드를 작성할 필요가 없습니다. 동기화는 타이틀이 실행되기 전에 이루어집니다.

코드 없는 클라우드 저장은 타이틀이 PC에서 더 이상 실행되고 있지 않을 때 업로드됩니다. 다음 조건 중 하나가 충족될 때 업로드가 발생합니다.

* 타이틀이 종료된 경우.
* 추적되는 사용자가 로그아웃한 경우.
* PC 전원 상태가 변경된 경우.
* 타이틀이 지정된 저장 영역에 마지막으로 쓴 지 30분이 경과한 경우.

코드 없는 클라우드 저장 솔루션은 `XGameSaveFiles` 위에 구축되었으며 파일 크기 및 사용자당 저장 한도와 관련된 모든 제한을 공유합니다. 파일은 64MB(또는 `XGameSave`나 Connected Storage와의 상호 운용이 필요한 경우 16MB)로 제한됩니다. 기본적으로 사용자당 저장 용량은 256MB로 제한됩니다. 더 큰 사용자당 저장 한도가 필요한 타이틀은 개발자 파트너 관리자(DPM)와 협력하여 예외를 요청할 수 있습니다.

<Note>
  디렉터리와 파일 이름에는 특정 명명 규칙과 문자 제한이 있습니다. 자세한 내용은 [XGameSaveFiles 경로 로직](/build/core-features/common/game-save/xgamesavefiles#xgamesavefiles-path-logic)을 참조하세요.
</Note>

코드 없는 클라우드 저장은 PC에서만 지원됩니다. 타이틀에는 [간소화된 사용자 모델(Simplified User Model)](/build/core-features/common/user/users-opting-into-simplified-model)이 필요합니다. 이것은 타이틀이 실행되기 전에 사용자가 로그인되어 있음을 보장합니다. 사용자가 타이틀에 로그인할 수 없으면 타이틀이 실행되지 않습니다. 게임 플레이 도중에 사용자가 로그아웃되면 타이틀이 종료됩니다.

<Info>
  코드 없는 클라우드 저장을 사용하려면 타이틀이 `wdapp install`을 사용하여 패키지된 빌드로 실행되어야 합니다. `.exe`를 직접 실행하면 클라우드 저장 리디렉션이 활성화되지 않습니다.

  패키지된 빌드가 실행되면 `NoCodePCRoot`를 통해 작성된 저장 파일이 `XGameSaveFiles`로 관리되는 스토리지로 리디렉션됩니다. 이후에 `.exe`를 직접 실행하면 실제의 `NoCodePCRoot` 폴더를 읽게 되는데, 이 폴더는 비어 있을 수 있어 저장 파일이 누락된 것처럼 보일 수 있습니다. 이 문제를 방지하려면 항상 `wdapp install`을 사용하여 패키지된 빌드로 코드 없는 클라우드 저장을 테스트하세요.
</Info>

### 코드 없는 클라우드 저장 활성화

코드 없는 클라우드 저장을 활성화하려면 다음 단계를 완료하세요.

1. `MicrosoftGame.config` 파일을 수정합니다.
2. 간소화된 사용자 모델을 활성화합니다.
3. 저장 파일의 루트 폴더를 지정합니다.
4. 타이틀에 해당하는 SCID를 제공합니다.

다음 코드 예제는 이 프로세스를 보여줍니다.

```xml theme={null}
<Game configVersion="1">
   <Identity Name="SampleNameOne" Publisher="CN=NoPublisher"/>
   <SaveGameStorage>
      <NoCodePCRoot RelativeTo="SavedGames">test\path</NoCodePCRoot>
      <SCID>DF9D8061-4790-4B84-86B4-CD060B00B4DD</SCID>
      <MaxUserQuota>256</MaxUserQuota>
   </SaveGameStorage>
   <!-- Content removed for brevity -->
   
   <!-- Must also opt into requiring a default user at launch -->
   <AdvancedUserModel>false</AdvancedUserModel>
</Game>
```

`NoCodePCRoot`에 지정하는 루트 폴더는 다음의 몇 가지 선택 사항 중 하나에 상대적이어야 합니다.

| RelativeTo        | PC의 폴더 위치                           |
| ----------------- | ----------------------------------- |
| `AppData`         | 환경 변수 %APPDATA%에 매핑됨                |
| `Public`          | 환경 변수 %PUBLIC%에 매핑됨                 |
| `LocalAppData`    | 환경 변수 %LOCALAPPDATA%에 매핑됨           |
| `LocalAppDataLow` | %USERPROFILE%\AppData\LocalLow에 매핑됨 |
| `ProgramData`     | 환경 변수 %PROGAMDATA%에 매핑됨             |
| `SavedGames`      | %USERPROFILE%\Saved Games에 매핑됨      |
| `UserProfile`     | 환경 변수 %USERPROFILE%에 매핑됨            |

<Info>
  `RelativeTo` 값으로 `SavedGames`를 사용하세요. Saved Games 폴더(`%USERPROFILE%\Saved Games`)는 Windows 알려진 폴더 ID인 `FOLDERID_SavedGames`에 해당합니다. OneDrive는 기본적으로 이 폴더를 동기화하지 않습니다.

  `AppData`(`%APPDATA%`)와 같은 다른 위치를 사용하지 마세요. OneDrive가 이러한 위치를 동기화할 수 있으며 클라우드 저장 동기화와 충돌을 일으킬 수 있습니다.

  `FOLDERID_SavedGames`에 대한 자세한 내용은 [SHGetKnownFolderPath](https://learn.microsoft.com/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath)를 참조하세요.
</Info>

*루트 디렉터리에 파일을 직접 배치할 수 없습니다*. 루트 폴더에서 최소한 하나의 하위 폴더 안에 중첩하세요. 예를 들어 `<NoCodePCRoot RelativeTo="SavedGames">savegame1.sav</NoCodePCRoot>`처럼 파일 이름을 직접 사용하는 것은 유효하지 않은데, savegame1.sav는 무시되기 때문입니다. `<NoCodePCRoot>`는 특정 파일이 아닌 디렉터리 경로를 정의하도록 만들어졌습니다.

## 코드 샘플

* [GameSaveCombo](https://learn.microsoft.com/samples/microsoft/xbox-gdk-samples/gamesavecombo/)
* [GameSaveFilesCombo](https://learn.microsoft.com/samples/microsoft/xbox-gdk-samples/gamesavefilescombo/)

## 참조 API 문서

* [XGameSaveFiles (API 콘텐츠)](/reference/system/xgamesavefiles/xgamesavefiles_members)
  * 함수
    * [XGameSaveFilesGetFolderWithUiAsync](/reference/system/xgamesavefiles/functions/xgamesavefilesgetfolderwithuiasync)

## 참고 항목

[게임 저장 TOC](/build/core-features/common/game-save/game-saves-toc)


## Related topics

- [게임 저장 개요](/ko/build/core-features/common/game-save/game-saves-overview.md)
- [GDKX로 첫 콘솔 타이틀 빌드 및 실행](/ko/home/build-first-title/first-console-title-walkthrough.md)
- [게임 저장](/ko/build/core-features/common/game-save/index.md)
- [인증(Certify)](/ko/publishing/game-publishing/concepts/certification/certification-overview.md)
- [저장소](/ko/build/console-features/storage/index.md)
