> ## 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 빠른 시작

> PlayFab Game Saves 빠른 시작에서는 초기 설정, SDK 호출, 클라우드 세이브 데이터 읽기 및 쓰기를 안내하여 세이브를 빠르게 통합할 수 있도록 합니다.

# Game Saves 빠른 시작

PlayFab Game Saves를 사용하면 플레이어가 세이브 데이터를 클라우드에 동기화하여 디바이스 간에 원활하게 진행 상황을 이어갈 수 있습니다. 이 빠른 시작 가이드는 XBOX 및 Windows 플랫폼에 대한 완전한 게임 세이브 솔루션을 구현하는 방법을 안내합니다.

## 사전 요구 사항

시작하기 전에 다음을 확인하세요:

* Game Saves에 [온보딩](/services/playfab/player-progression/game-saves/onboarding) 완료
* [개요](/services/playfab/player-progression/game-saves/overview) 섹션의 구현 요구 사항 검토 완료
* 아래에 나열된 요구 사항 완료
* (선택 사항) GitHub에서 Windows용 엔드투엔드 **Game Saves 샘플**을 복제하거나 검토: [PlayFabGameSaveSample-Windows](https://github.com/PlayFab/PlayFab-Samples/tree/master/Samples/All/PlayFabGameSaveSample-Windows). 이 샘플은 이 빠른 시작에서 참조하는 초기화, 동기화, 충돌 처리, 업로드 흐름을 보여줍니다.

## 배울 내용

이 가이드에서는 다음 방법을 배웁니다:

* Game Saves 시스템 초기화
* 클라우드에서 기존 세이브 데이터 다운로드
* 로컬 세이브 데이터를 클라우드에 업로드
* 충돌 및 UI 콜백 처리
* 활성 디바이스 시나리오 관리

## 개발 요구 사항

### 소프트웨어 요구 사항

* [PlayFab 개발자 계정](https://developer.playfab.com)
* Gaming Runtime 개발에는 Visual Studio 2019 또는 Visual Studio 2022가 권장됩니다. 자세한 내용은 [https://learn.microsoft.com/en-us/gaming/gdk/docs/gdk-dev/get-started/overviews/sdk-and-tools#install-visual-studio](https://learn.microsoft.com/en-us/gaming/gdk/docs/gdk-dev/get-started/overviews/sdk-and-tools#install-visual-studio) 를 참조하세요.
* 최신 [Microsoft Game Development Kit (GDK)](https://learn.microsoft.com/gaming/gdk/) 액세스

## Game Saves 흐름 개요

Game Saves 시스템은 디바이스 간에 원활하게 작동하는 간단한 패턴을 따릅니다:

### 초기 설정 (게임 세션당 한 번)

1. **서비스 초기화**: PlayFab Core 및 Game Saves 모듈 설정
2. **사용자 인증**: XBOX 인증을 사용하여 플레이어 로그인
3. **기존 세이브 다운로드**: 다른 디바이스의 세이브 데이터를 로컬 디바이스에 동기화
4. **세이브 위치 가져오기**: 게임이 세이브 파일을 써야 하는 로컬 세이브 루트 폴더 얻기

### 게임플레이 중

5. **세이브 파일 쓰기**: 게임이 평소처럼 로컬 세이브 루트 폴더에 세이브 데이터를 씀
6. **변경 사항 업로드**: 수정된 세이브 파일을 주기적으로 클라우드에 업로드
7. **계속 플레이**: 게임 세션 중 필요에 따라 5-6단계 반복

### 세션 종료

8. **최종 업로드**: 플레이어가 종료하기 전에 최종 변경 사항 업로드
9. **백그라운드 동기화**: XBOX/Windows에서는 게임이 닫힐 때 시스템이 자동으로 최종 업로드를 처리

### 주요 이점

* **오프라인 지원**: 플레이어는 인터넷 연결 없이도 게임을 시작할 수 있음
* **자동 충돌 해결**: 내장 UI가 디바이스 간 세이브 충돌을 처리
* **증분 업로드**: 변경된 파일만 업로드되어 성능 향상
* **크로스 디바이스 연속성**: 디바이스 간 전환 시 원활한 경험

## 구현 세부 정보

다음 섹션은 각 단계에 대한 자세한 코드 예제를 제공합니다:

## 1단계: Game Saves 초기화

Game Saves는 온라인과 오프라인 모두에서 작동하도록 설계되어 다른 PlayFab API와 다릅니다. 디바이스가 오프라인으로 시작해도 작동하는 지속적인 로컬 사용자 ID를 유지합니다.

### 주요 개념

* **PFLocalUserHandle**: 오프라인에서 작동하는 지속적인 사용자 식별자
* **PFServiceConfigHandle**: PlayFab 타이틀에 대한 구성
* **오프라인 우선 설계**: 인터넷 연결이 없어도 시스템이 즉시 작동

### 사전 요구 사항

Game Saves를 초기화하기 전에 다음을 확인하세요:

* XBOX 런타임을 초기화하기 위해 `XGameRuntimeInitialize()`를 호출했는지
* 사용자에 로그인하고 `XUserHandle`을 얻기 위해 `XUserAddAsync()`를 호출했는지
* Game Manager의 PlayFab Title ID

### 구현

```cpp theme={null}
// Step 1: Initialize PlayFab Core
HRESULT hr = PFInitialize(nullptr);
if (FAILED(hr))
{
    // Handle initialization failure - log error and exit gracefully
    return hr;
}

// Step 2: Create service config handle with your title information
PFServiceConfigHandle serviceConfigHandle{ nullptr };
hr = PFServiceConfigCreateHandle(
    "https://<titleId>.playfabapi.com",    // Replace <titleId> with your actual PlayFab Title ID
    "<titleId>",                           // Replace <titleId> with your actual PlayFab Title ID
    &serviceConfigHandle);
if (FAILED(hr))
{
    // Handle service config creation failure
    return hr;
}

// Step 3: Initialize the Game Saves module
PFGameSaveInitArgs args = {};
// Set args.saveFolder here if you are targetting platforms such as Steam
// where you need to provide root of where the game saves are
hr = PFGameSaveFilesInitialize(&args);
if (FAILED(hr))
{
    // Handle Game Saves initialization failure
    return hr;
}

// Step 4: Create a local user handle
// NOTE: Assumes you have already obtained 'xuserHandle' from XUserAddAsync
PFLocalUserHandle localUserHandle;
hr = PFLocalUserCreateHandleWithXboxUser(serviceConfigHandle, xuserHandle, nullptr, &localUserHandle);
if (FAILED(hr))
{
    // Handle local user creation failure
    return hr;
}

// Success! The Game Saves system is now initialized and ready to use
```

<Info>
  `<titleId>`를 Game Manager의 실제 PlayFab Title ID로 바꾸세요. `xuserHandle`은 `XUserAddAsync`의 성공적인 호출에서 얻어야 합니다.
</Info>

### 대체 플랫폼

XBOX 인증이 없고 오프라인 지원이 없는 플랫폼의 경우 다른 버전의 `PFLocalUserCreateHandle` 또는 `PFLocalUserCreateHandleWithPersistedLocalId`를 사용하세요. 구현 세부 정보는 플랫폼별 문서를 참조하세요.

예:

```cpp theme={null}
PFLocalUserHandle localUserHandle;
hr = PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, nullptr, &localUserHandle);
if (FAILED(hr))
{
    // Handle local user creation failure
    return hr;
}
```

## 2단계: 클라우드에서 세이브 데이터 동기화

초기화 후, 다른 디바이스에서 기존 세이브 데이터를 동기화하기 위해 Game Saves 시스템에 사용자를 추가합니다. 이 단계에서는 게임이 세이브 파일을 읽고 쓸 로컬 세이브 루트 폴더도 설정합니다.

### 언제 호출하나

* 사용자 인증 후 게임 세션당 한 번
* 사용자가 게임의 메인 메뉴로 돌아왔을 때
* 일시 중단/백그라운드에서 재개한 후

### 이 단계가 하는 일

1. 다른 디바이스에서 **기존 세이브를 다운로드** (새 파일 또는 변경된 파일만)
2. 적절한 버전 관리를 위해 가능한 경우 **파일 타임스탬프 보존**
3. 내장 UI를 통해 자동으로 **충돌 처리**
4. 이 사용자에 대해 **디바이스를 활성으로 설정**
5. 게임이 파일을 써야 하는 **세이브 폴더 경로 제공**

### 중요한 제한 사항

* Game Saves 세션당 **한 번만 성공적으로** 호출할 수 있음
* 다시 호출하려면 Game Saves 시스템을 다시 초기화해야 함
* 충돌, 저장소 문제, 디바이스 경합에 대한 UI 프롬프트를 트리거함

### 구현

```cpp theme={null}
// Add user to Game Saves system and sync from cloud
HRESULT hr;
XAsyncBlock async{};
hr = PFGameSaveFilesAddUserWithUiAsync(localUserHandle, PFGameSaveFilesAddUserOptions::None, &async);
if (FAILED(hr))
{
    // Handle API call failure
    return hr;
}

// Wait for the operation to complete
// For production code, consider using a callback instead of blocking
hr = XAsyncGetStatus(&async, true); 
if (FAILED(hr))
{
    // Handle async operation failure (network issues, user cancellation, etc.)
    return hr;
}

hr = PFGameSaveFilesAddUserWithUiResult(&async);
if (FAILED(hr))
{
    // Handle specific operation failures (conflicts, storage issues, etc.)
    return hr;
}

// Get the local save root folder path for your game
char saveFolder[1024] = { 0 };
hr = PFGameSaveFilesGetFolder(localUserHandle, 1024, saveFolder, nullptr);
if (FAILED(hr))
{
    // Handle folder retrieval failure
    return hr;
}

// Check remaining cloud storage quota
int64_t remainingQuota{ 0 };
hr = PFGameSaveFilesGetRemainingQuota(localUserHandle, &remainingQuota);
if (FAILED(hr))
{
    // Handle quota retrieval failure
    return hr;
}

// Success! You can now read/write save files in the saveFolder directory
printf("Save folder: %s\n", saveFolder);
printf("Remaining quota: %lld bytes\n", remainingQuota);
```

### 다음 단계

이 호출이 성공적으로 완료된 후:

* 게임은 `saveFolder` 디렉터리에서 기존 세이브 파일을 읽을 수 있음
* 필요에 따라 새 세이브 파일을 쓰고 하위 디렉터리를 만듬
* 이제 디바이스는 이 사용자에 대해 "활성"으로 간주됨
* 사용자가 다른 디바이스에서 동기화를 시도하면 경고가 표시됨

## 3단계: 세이브 데이터를 클라우드에 업로드

게임이 로컬 세이브 루트 폴더에 세이브 파일과 하위 폴더를 쓴 후, 이 단계를 사용하여 변경 사항을 클라우드에 업로드합니다. 시스템은 마지막 업로드 이후 변경된 파일과 하위 폴더만 자동으로 감지하고 업로드합니다. 파일 및 폴더 삭제도 자동으로 클라우드에 동기화됩니다.

### 업로드하기 좋은 제안 시점

* **상당한 진행 후**: 플레이어가 체크포인트에 도달하거나 레벨을 완료했을 때
* **메뉴 전환 전**: 메인 메뉴로 돌아오거나 게임 모드를 전환할 때
* **게임 종료 시**: 플레이어가 게임을 종료하기 전
* **주기적인 세이브**: 장시간의 게임플레이 세션 중 몇 분마다

### 업로드 옵션

* **`KeepDeviceActive`**: 디바이스가 활성 상태로 유지되어 나중에 추가 업로드 허용
* **`ReleaseDeviceAsActive`**: 디바이스를 활성 상태에서 해제하여 다른 디바이스에서 원활한 동기화 허용

### 플랫폼 동작

* **XBOX/Windows**: 게임이 닫힌 후에도 백그라운드에서 업로드 계속
* **기타 플랫폼** (Steam Deck 등): 게임 종료 전에 업로드가 완료되어야 하며, 그렇지 않으면 세이브 데이터가 클라우드에 도달하지 않음

### 구현

```cpp theme={null}
// Upload save files to cloud
XAsyncBlock async{};
HRESULT hr = PFGameSaveFilesUploadWithUiAsync(
    localUserHandle, 
    PFGameSaveFilesUploadOption::KeepDeviceActive,  // Use ReleaseDeviceAsActive when quitting
    &async);
if (FAILED(hr))
{
    // Handle API call failure
    return hr;
}

// Wait for upload to complete
// Consider using callbacks for better user experience
hr = XAsyncGetStatus(&async, true); 
if (FAILED(hr))
{
    // Handle async operation failure (network issues, storage full, etc.)
    return hr;
}

hr = PFGameSaveFilesUploadWithUiResult(&async);
if (FAILED(hr))
{
    // Handle upload failure
    return hr;
}

// Success! Save data is now safely stored in the cloud
```

### 언제 세이브 폴더에 다시 쓸 수 있나요?

업로드하는 동안 시스템은 로컬 세이브 파일을 읽고 압축한 후 업로드합니다. 동기화 상태가 `Uploading`으로 전환되면(`PFGameSaveFilesUiProgressCallback`을 통해 보고됨), 시스템은 파일 읽기를 마쳤으므로 세이브 폴더에 다시 쓰는 것이 안전합니다. 세이브를 재개하기 전에 전체 업로드가 완료될 때까지 기다릴 필요는 없습니다.

진행 콜백을 사용하지 않는 경우, 새 세이브 데이터를 쓰기 전에 `XAsyncBlock`이 완료될 때까지 기다리세요.

### 모범 사례

1. **실패를 우아하게 처리**: 네트워크 문제가 게임을 충돌시켜서는 안 됩니다
2. **적절한 옵션 사용**:
   * 추가 업로드를 위한 게임플레이 중에는 `KeepDeviceActive` 사용
   * 플레이어가 종료하거나 메뉴로 돌아갈 때는 `ReleaseDeviceAsActive` 사용
3. **XBOX 이외의 플랫폼에서 사용자에게 경고**: 플레이어에게 업로드 중에 종료하지 말라고 알림

### 빈도 고려 사항

* 세션당 여러 업로드가 지원되며 효율적임
* 변경된 파일만 업로드되어 대역폭 사용 최소화
* 특정 할당량 및 제한에 대해서는 [제한 문서](/services/playfab/player-progression/game-saves/limits)를 참조하세요

## 4단계: UI 콜백 처리 (선택 사항)

Game Saves는 XBOX 및 Windows 플랫폼용 내장 UI를 제공합니다. 다른 플랫폼(예: Steam Deck)에서는 게임이 콜백을 처리하여 자체 UI를 제공해야 합니다.

UI 콜백은 `PFGameSaveFilesAddUserWithUiAsync` 및 `PFGameSaveFilesUploadWithUiAsync` 중에 실행됩니다. 각 콜백은 게임이 응답할 때까지 비동기 작업을 일시 중지합니다—모든 UI 콜백이 해결될 때까지 `XAsyncBlock` 콜백은 실행되지 않습니다.

```cpp theme={null}
// Set up custom UI callbacks (call this before AddUser or Upload operations)
// See sample for detailed examples of these callbacks.
PFGameSaveUICallbacks callbacks{};
callbacks.progressCallback = MyProgressCallback;
callbacks.syncFailedCallback = MySyncFailedCallback;
callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback;
callbacks.conflictCallback = MyConflictCallback;
callbacks.outOfStorageCallback = MyOutOfStorageCallback;

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

콜백 유형, 응답 API, 사용자 액션의 전체 목록과 상태 머신의 작동 방식에 대한 자세한 내용은 [Game Saves UI 콜백](/services/playfab/player-progression/game-saves/ui-callbacks)을 참조하세요.

## 세이브 충돌 이해

세이브 충돌은 동일한 게임 데이터가 여러 디바이스에서 수정된 경우 발생합니다. Game Saves는 각 루트 수준의 하위 폴더를 충돌 해결을 위한 원자적 단위로 취급하며, 플레이어는 충돌이 발생할 때 로컬 또는 클라우드 데이터 중 하나를 유지하도록 선택할 수 있습니다.

자세한 충돌 처리 시나리오 및 모범 사례는 [Game Saves 충돌](/services/playfab/player-progression/game-saves/conflicts)을 참조하세요.

## Game Saves 오프라인 모드 이해

Game Saves는 온라인과 오프라인 모두에서 작동합니다. 클라우드에 연결되어 있을 때 모든 API가 정상적으로 작동합니다. 오프라인 또는 연결이 끊긴 경우 로컬 세이브는 계속 작동하지만 클라우드 작업은 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD`를 반환합니다.

`PFGameSaveFilesIsConnectedToCloud()`를 사용하여 연결 상태를 확인하고 네트워크 문제를 원활하게 처리하기 위한 동기화 실패 콜백을 구현하세요.

자세한 오프라인 동작 및 모범 사례는 [Game Saves 오프라인 모드](/services/playfab/player-progression/game-saves/offline)를 참조하세요.

## Game Saves 활성 디바이스 변경 이해

플레이어가 세션 중에 디바이스를 전환할 때, 여러 디바이스에서 동시에 플레이하여 실수로 진행 상황을 잃지 않도록 하는 것이 중요합니다.

게임이 XBOX의 **단일 존재 지점(SPOP)** 기능만 사용하여 로그인하는 경우, 이 시나리오는 자동으로 방지됩니다. SPOP는 사용자가 한 번에 하나의 XBOX 디바이스에서만 로그인할 수 있도록 보장합니다. 그렇지 않으면 플레이어가 세션 중에 디바이스를 전환하는 시나리오를 처리하기 위해 활성 디바이스 변경 콜백도 구현해야 합니다.

자세한 동작 및 모범 사례는 [Game Saves 활성 디바이스 변경](/services/playfab/player-progression/game-saves/activedevicechanges)을 참조하세요.

## 디버깅

SDK의 결과를 확인하고 호출을 디버그하는 가장 쉬운 방법은 [디버그 추적](/services/playfab/sdks/c/tracing)을 활성화하는 것입니다. 디버그 추적을 활성화하면 디버거 출력 창에서 결과를 볼 수 있으며 결과를 게임 자체의 로그에 연결할 수 있습니다.


## Related topics

- [Game Saves UI 콜백](/ko/services/playfab/player-progression/game-saves/ui-callbacks.md)
- [2025년 10월 GDK를 사용한 Game Saves 구현](/ko/services/playfab/player-progression/game-saves/october-2025-gdk-changes.md)
- [PlayFab Game Saves용 계정 연결 전략](/ko/services/playfab/player-progression/game-saves/linking.md)
- [PlayFab Game Saves용 Steam Deck 구현 가이드](/ko/services/playfab/player-progression/game-saves/steam-deck-implementation.md)
- [Game Manager 빠른 시작](/ko/services/playfab/live-service-management/gamemanager/quickstart.md)
