> ## 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 UI 콜백

> 콜백을 등록하고, 상태 머신을 처리하며, 충돌 및 재시도를 위한 응답 API를 호출하여 PlayFab Game Saves에 대한 사용자 지정 동기화 UI를 구현합니다.

Game Saves는 게임이 동기화 작업 중 이벤트에 응답할 수 있도록 하는 UI 콜백 세트를 제공합니다. XBOX 및 Windows에서는 플랫폼이 이러한 이벤트에 대한 내장 UI를 제공합니다. 다른 플랫폼(예: Steam Deck)에서는 게임이 이러한 콜백을 처리하여 자체 UI를 구현해야 합니다.

XBOX 및 Windows에서 콜백을 설정하면 플랫폼에서 제공하는 UI가 구현으로 재정의됩니다. 게임이 모든 플랫폼에서 일관된 플레이어 경험을 필요로 하는 경우 유용합니다 — 모든 곳에 동일한 콜백을 등록하면 내장 UI가 나타나지 않습니다.

## 상태 머신 작동 방식

Game Saves는 UI 콜백을 비동기 작업 수명 주기와 조정하기 위해 내부 상태 머신을 사용합니다. UI 콜백이 실행되면 비동기 작업이 일시 중지됩니다 — 콜백이 해결될 때까지 `XAsyncBlock` 콜백은 실행되지 않습니다. 게임이 해당 응답 API를 호출하거나 비동기 작업이 취소될 때까지 상태 머신은 진행되지 않습니다.

이는 다음을 의미합니다:

* 각 콜백 유형에는 해당하는 응답 API가 있습니다. 다음에 무엇을 할지 시스템에 알리려면 응답 API를 호출하세요.
* 응답 API는 콜백 함수 내부 또는 외부에서 호출할 수 있습니다.
* 응답 액션이 `Retry`인 경우 작업이 재시도되고 동일한 콜백을 다시 트리거할 수 있습니다.
* `XAsyncBlock` 콜백은 작업이 최종 상태(성공, 취소 또는 오프라인 대체)에 도달한 후에만 실행됩니다.

예를 들어, 속도 제한으로 인해 업로드가 실패한 경우:

1. `PFGameSaveFilesUiSyncFailedCallback`이 오류와 함께 실행됩니다.
2. `XAsyncBlock` 콜백은 아직 실행되지 않습니다 — 상태 머신이 응답을 기다립니다.
3. 사용자가 `Retry`를 선택하고 재시도도 실패하면 sync failed 콜백이 다시 실행됩니다.
4. 사용자가 `Cancel`을 선택하면 `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다.
5. 재시도가 성공하면 `XAsyncBlock` 콜백이 `S_OK`로 실행됩니다.

## 콜백이 트리거되는 시점

UI 콜백은 두 가지 비동기 작업 중에만 실행됩니다:

| 작업                                  | 트리거할 수 있는 콜백                                                              |
| ----------------------------------- | ------------------------------------------------------------------------- |
| `PFGameSaveFilesAddUserWithUiAsync` | Progress, Sync Failed, Active Device Contention, Conflict, Out of Storage |
| `PFGameSaveFilesUploadWithUiAsync`  | Progress, Sync Failed                                                     |

## 콜백 등록

`PFGameSaveFilesAddUserWithUiAsync` 또는 `PFGameSaveFilesUploadWithUiAsync`를 호출하기 전에 모든 콜백을 등록하세요:

```cpp theme={null}
PFGameSaveUICallbacks callbacks{};
callbacks.progressCallback = MyProgressCallback;
callbacks.progressContext = nullptr;
callbacks.syncFailedCallback = MySyncFailedCallback;
callbacks.syncFailedContext = nullptr;
callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback;
callbacks.activeDeviceContentionContext = nullptr;
callbacks.conflictCallback = MyConflictCallback;
callbacks.conflictContext = nullptr;
callbacks.outOfStorageCallback = MyOutOfStorageCallback;
callbacks.outOfStorageContext = nullptr;

HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks);
```

## 콜백 참조

### Progress

업로드 또는 다운로드 진행 상황을 보고합니다. 콜백 내부에서 `PFGameSaveFilesUiProgressGetProgress`를 사용하여 현재 `PFGameSaveFilesSyncState`, 완료된 바이트 및 전체 바이트를 검색합니다.

**콜백**: `PFGameSaveFilesUiProgressCallback`

**응답 API**: `PFGameSaveFilesSetUiProgressResponse`

| 액션       | 효과                                                                  |
| -------- | ------------------------------------------------------------------- |
| `Cancel` | 작업을 취소합니다. `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다. |

<Note>
  진행 콜백은 계속 진행하기 위해 응답이 필요하지 않습니다 — 작업은 자체적으로 계속 진행됩니다. 사용자가 취소하려는 경우에만 응답 API를 호출하세요.
</Note>

#### 동기화 상태

`PFGameSaveFilesSyncState` 열거형은 작업이 어느 단계에 있는지를 나타냅니다:

| 상태                     | 설명                         | 세이브 폴더에 쓰기 안전? |
| ---------------------- | -------------------------- | -------------- |
| `NotStarted`           | 작업이 시작되지 않음                | 예              |
| `PreparingForDownload` | 클라우드에서 다운로드 준비 중           | 예              |
| `Downloading`          | 클라우드에서 다운로드 중              | 아니요            |
| `PreparingForUpload`   | 로컬 파일 읽기 및 압축 중            | 아니요            |
| `Uploading`            | 클라우드로 업로드 진행 중 (로컬 파일 캡처됨) | 예              |
| `SyncComplete`         | 작업 완료                      | 예              |

### Sync failed

예를 들어 네트워크 문제나 속도 제한으로 인해 동기화 작업이 실패할 때 실행됩니다.

**콜백**: `PFGameSaveFilesUiSyncFailedCallback`

**매개변수**: `PFGameSaveFilesSyncState`(실패한 단계)와 `HRESULT`(오류 코드)를 수신합니다.

**응답 API**: `PFGameSaveFilesSetUiSyncFailedResponse`

| 액션           | 효과                                                                                                                                                            |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Cancel`     | 작업을 취소합니다. `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다.                                                                                           |
| `Retry`      | 실패한 작업을 재시도합니다. 재시도가 실패하면 이 콜백이 다시 실행됩니다.                                                                                                                     |
| `UseOffline` | `PFGameSaveFilesAddUserWithUiAsync` 중에만 유효합니다. `XAsyncBlock` 콜백이 `S_OK`로 실행되지만 시스템이 오프라인 모드로 진입합니다. 이 상태를 감지하려면 `PFGameSaveFilesIsConnectedToCloud()`를 사용하세요. |

오프라인 모드 동작에 대한 자세한 내용은 [Game Saves 오프라인 모드](/services/playfab/player-progression/game-saves/offline)를 참조하세요.

### Active device contention

다른 디바이스가 이미 이 사용자의 활성 디바이스인 경우 `PFGameSaveFilesAddUserWithUiAsync` 중에 실행됩니다. 콜백은 로컬 및 원격 세이브 데이터 모두에 대한 `PFGameSaveDescriptor` 구조체를 수신하며, 사용자가 결정하는 데 도움이 되도록 표시할 수 있는 디바이스 이름, 타임스탬프 및 세이브 크기를 포함합니다.

**콜백**: `PFGameSaveFilesUiActiveDeviceContentionCallback`

**응답 API**: `PFGameSaveFilesSetUiActiveDeviceContentionResponse`

| 액션                  | 효과                                                                                   |
| ------------------- | ------------------------------------------------------------------------------------ |
| `Cancel`            | 작업을 취소합니다. `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다.                  |
| `Retry`             | 재시도합니다 — 사용자가 다른 디바이스가 곧 해제될 것으로 예상하는 경우 유용합니다. 다른 디바이스가 여전히 활성 상태이면 이 콜백이 다시 실행됩니다. |
| `SyncLastSavedData` | 로컬 디바이스를 활성으로 만들고 동기화합니다. 원격 디바이스는 더 이상 업로드할 수 없으며 활성 디바이스 변경 알림을 받습니다.              |

활성 디바이스 동작에 대한 자세한 내용은 [Game Saves 활성 디바이스 변경](/services/playfab/player-progression/game-saves/activedevicechanges)을 참조하세요.

### Conflict

로컬 및 클라우드 세이브 데이터가 갈라진 경우 `PFGameSaveFilesAddUserWithUiAsync` 중에 실행됩니다. 콜백은 로컬 및 원격 세이브 데이터 모두에 대한 `PFGameSaveDescriptor` 구조체를 수신합니다.

**콜백**: `PFGameSaveFilesUiConflictCallback`

**응답 API**: `PFGameSaveFilesSetUiConflictResponse`

| 액션           | 효과                                                                  |
| ------------ | ------------------------------------------------------------------- |
| `Cancel`     | 작업을 취소합니다. `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다. |
| `TakeLocal`  | 로컬 세이브 데이터를 유지하고 클라우드에 업로드합니다.                                      |
| `TakeRemote` | 로컬 변경 사항을 폐기하고 클라우드 세이브 데이터를 다운로드합니다.                               |

<Info>
  충돌 해결은 개별 파일이나 폴더가 아닌 전체 세이브에 적용됩니다. 원자적 단위 수준에서 충돌이 어떻게 감지되고 전역적으로 해결되는지에 대한 자세한 내용은 [Game Saves 충돌](/services/playfab/player-progression/game-saves/conflicts)을 참조하세요.
</Info>

### Out of storage

로컬 디바이스에 클라우드에서 세이브 데이터를 다운로드할 충분한 디스크 공간이 없는 경우 `PFGameSaveFilesAddUserWithUiAsync` 중에 실행됩니다. 콜백은 얼마나 많은 공간이 필요한지 나타내는 `requiredBytes`를 수신합니다.

**콜백**: `PFGameSaveFilesUiOutOfStorageCallback`

**응답 API**: `PFGameSaveFilesSetUiOutOfStorageResponse`

| 액션       | 효과                                                                  |
| -------- | ------------------------------------------------------------------- |
| `Cancel` | 작업을 취소합니다. `XAsyncBlock` 콜백이 `E_PF_GAMESAVE_USER_CANCELLED`로 실행됩니다. |
| `Retry`  | 사용자가 로컬 저장소 공간을 확보한 후 재시도합니다. 여전히 공간이 충분하지 않으면 이 콜백이 다시 실행됩니다.      |

## 플랫폼 요구 사항

| 플랫폼                       | UI 콜백                                          |
| ------------------------- | ---------------------------------------------- |
| **XBOX 및 Windows**        | 선택 사항. 내장 UI를 재정의하려면 콜백을 설정하세요.                |
| **기타 플랫폼** (Steam Deck 등) | **필수**. 내장 UI를 사용할 수 없으므로 게임이 모든 콜백을 처리해야 합니다. |

Steam Deck 구현 세부 정보는 [Steam Deck 구현 가이드](/services/playfab/player-progression/game-saves/steam-deck-implementation)를 참조하세요.

## 관련 콘텐츠

* [Game Saves 빠른 시작](/services/playfab/player-progression/game-saves/quickstart)
* [Game Saves 오프라인 모드](/services/playfab/player-progression/game-saves/offline)
* [Game Saves 충돌](/services/playfab/player-progression/game-saves/conflicts)
* [Game Saves 활성 디바이스 변경](/services/playfab/player-progression/game-saves/activedevicechanges)


## Related topics

- [Game Saves 빠른 시작](/ko/services/playfab/player-progression/game-saves/quickstart.md)
- [PlayFab Game Saves용 Steam Deck 구현 가이드](/ko/services/playfab/player-progression/game-saves/steam-deck-implementation.md)
- [Game Saves 개요](/ko/services/playfab/player-progression/game-saves/overview.md)
- [Game Saves 오프라인 모드](/ko/services/playfab/player-progression/game-saves/offline.md)
- [Game Saves 롤백](/ko/services/playfab/player-progression/game-saves/rollback.md)
