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

# 타이틀 관리 업적 업데이트

> XblAchievementsUpdateAchievementAsync를 사용하여 타이틀 관리형 XBOX services 업적을 잠금 해제하거나 완료 진행률을 보고하는 방법을 보여 주는 XSAPI 예제 코드입니다.

이 항목에서는 다음을 다룹니다.

* [시작하기 전에](#before-you-begin)
* [업적 잠금 해제](#unlocking-an-achievement)
* [업적의 완료 진행률 업데이트](#updating-an-achievement)
* [문제 해결](#troubleshooting)

## 시작하기 전에

* 제품에서 전체 XBOX services 기능 집합을 사용합니다. 새 제품은 제한된 XBOX services로 시작하며, 제품이 온보딩될 때까지 업적과 게이머스코어를 사용할 수 없습니다. 자세한 내용은 [전체 XBOX services를 사용하도록 제품 온보딩 요청](https://docs.xbox.com/ko/home/onboarding.md#request-product-onboarding-to-enable-full-xbox-services)을 참조하세요.
* Partner Center에서 업적을 구성하고 XBOX services 구성을 개발 샌드박스에 게시했습니다. 자세한 내용은 [Partner Center에서 타이틀 관리 업적 구성](https://docs.xbox.com/ko/services/xbox-services/player-data/achievements/title-managed/config/live-achievements-tm-config.md)을 참조하세요.
* 개발 키트 또는 Windows PC가 같은 개발 샌드박스를 사용하며, 해당 샌드박스에 액세스할 수 있는 테스트 계정으로 로그인합니다. 자세한 내용은 [XBOX services 샌드박스 개요](https://docs.xbox.com/ko/services/xbox-services/fundamentals/sandboxes/live-setup-sandbox.md)를 참조하세요.
* 게임에서 Gaming Runtime을 초기화한 다음 `scid` 멤버에 서비스 구성 ID(SCID)가 포함된 [XblInitArgs](https://docs.xbox.com/ko/reference/live/xsapi-c/xbox_live_global_c/structs/xblinitargs.md) 구조체를 사용하여 [XblInitialize](https://docs.xbox.com/ko/reference/live/xsapi-c/xbox_live_global_c/functions/xblinitialize.md)를 호출했습니다. SCID는 대/소문자를 구분합니다. 자세한 내용은 [XBOX services API 사용 방법](https://docs.xbox.com/ko/services/xbox-services/fundamentals/xbox-services-api/live-gs-xbl-apis.md)을 참조하세요.
* 사용자를 로그인시키고 [XblContextCreateHandle](https://docs.xbox.com/ko/reference/live/xsapi-c/xbox_live_context_c/functions/xblcontextcreatehandle.md)을 호출하여 해당 사용자에 대한 `XblContextHandle`을 만들었습니다.

테스트 실행 사이에 테스트 계정의 업적을 초기화하려면 [Player Data Reset 도구(XblPlayerDataReset.exe)](https://docs.xbox.com/ko/tools/tools-services/live-player-data-reset.md)를 사용하세요. XUID로 플레이어를 초기화하려면 XblDevAccount.exe를 사용하여 로그인하는 개발자 계정에 제품 수준의 Tools Access 권한이 있어야 합니다.

## 업적 잠금 해제

업적이 Partner Center를 통해 구성되고 개발 샌드박스에 게시된 후 타이틀은 [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md) API를 호출하여 업적을 잠금 해제할 수 있습니다.
자세한 내용은 다음 섹션의 예제 코드를 참조하세요.

업적을 잠금 해제하려면 `percentComplete`를 100으로 설정합니다.
사용자가 온라인 상태이면 요청이 XBOX 서비스 업적 서비스로 즉시 전송되고 다음과 같은 사용자 환경이 트리거됩니다.

* 사용자에게 업적 잠금 해제 알림이 표시됩니다.
* 지정된 업적이 타이틀의 사용자 업적 목록에서 잠금 해제된 것으로 표시됩니다.
* 잠금 해제된 업적이 사용자의 활동 피드에 추가됩니다.

> [!NOTE]
>
> 사용자 환경은 이벤트 기반 업적이나 타이틀 관리 업적을 사용하는 업적에 대해 시각적으로 동일합니다.

사용자가 오프라인 상태인 경우 잠금 해제 요청은 사용자 디바이스에 로컬로 대기열에 넣어집니다.
네트워크 연결이 다시 설정되면 요청이 자동으로 업적 서비스로 전송되며(게임에서 이를 트리거하기 위한 작업은 필요하지 않음) 앞서 설명한 사용자 환경이 발생합니다.

## 업적의 완료 진행률 업데이트

업적을 잠금 해제하기 위한 사용자의 진행률을 업데이트하려면 [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md)를 호출합니다. `percentComplete` 인수를 1-100 사이의 정수로 설정합니다.
자세한 내용은 다음 예제 코드를 참조하세요.

업적의 진행률은 증가만 할 수 있습니다.
`percentComplete`가 업적의 마지막 `percentComplete` 값보다 작은 숫자로 설정되면 업데이트는 무시됩니다.
예를 들어 업적의 `percentComplete`가 이전에 75로 설정된 경우 값이 25인 업데이트를 보내면 무시됩니다. 업적은 여전히 75% 완료된 것으로 표시됩니다.

`percentComplete`가 100으로 설정되면 업적이 잠금 해제됩니다.

`percentComplete`가 100보다 큰 숫자로 설정되면 API는 숫자를 정확히 100으로 설정한 것처럼 동작합니다.

### 현재 타이틀의 업적 업데이트

다음과 같이 [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md)를 호출하여 현재 타이틀의 업적을 업데이트할 수 있습니다.

**Flat C API**

```cpp theme={null}
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementAsync(
    xboxLiveContext,
    xboxUserId,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}
```

자세한 내용은 다음을 참조하세요.

* [XAsyncBlock](https://docs.xbox.com/ko/reference/system/xasync/structs/xasyncblock.md)
* [XAsyncGetStatus](https://docs.xbox.com/ko/reference/system/xasync/functions/xasyncgetstatus.md)
* [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md)

### 다른 타이틀의 업적 업데이트

다음과 같이 [XblAchievementsUpdateAchievementForTitleIdAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementfortitleidasync.md)를 사용하여 다른 `titleId`의 업적을 업데이트할 수 있습니다.

**Flat C API**

```cpp theme={null}
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementForTitleIdAsync(
    xboxLiveContext,
    xboxUserId,
    titleId,
    scid,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}
```

자세한 내용은 다음을 참조하세요.

* [XAsyncBlock](https://docs.xbox.com/ko/reference/system/xasync/structs/xasyncblock.md)
* [XAsyncGetStatus](https://docs.xbox.com/ko/reference/system/xasync/functions/xasyncgetstatus.md)
* [XblAchievementsUpdateAchievementForTitleIdAsync](https://docs.xbox.com/ko/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementfortitleidasync.md)

## 문제 해결

실패 HRESULT를 대응 가능한 범주로 분류하려면 [XblGetErrorCondition](https://docs.xbox.com/ko/reference/live/xsapi-c/errors_c/functions/xblgeterrorcondition.md)을 호출하세요.

실패한 업데이트를 직접 다시 시도하지 마세요. 네트워크 또는 인증 문제, 제한(HTTP 429), 서버 오류(HTTP 5xx) 또는 분류되지 않은 오류로 인해 업데이트가 실패하면 XSAPI는 이를 오프라인 이벤트로 큐에 넣고 장치가 다시 온라인 상태가 되면 전송합니다. 이 경우 `XAsyncGetStatus`는 이벤트를 큐에 넣은 결과를 반환하며, 일반적으로 `S_OK`입니다. 다시 시도하면 서비스에서 업데이트를 두 번 받을 수 있습니다.

게임에 다음과 같은 결과가 전달될 수 있습니다.

| 결과 | 가능한 원인 | 조치 |
| - | - | - |
| `HTTP_E_STATUS_NOT_MODIFIED` (`XblErrorCondition::Http304NotModified`) | 업적이 이미 잠금 해제되었거나 새 진행률 값이 서비스에 기록된 값보다 높지 않습니다. | 조치가 필요하지 않습니다. |
| 400, 403, 404와 같은 기타 HTTP 4xx 상태 | 예를 들어 업적 ID가 타이틀 또는 샌드박스에 구성되어 있지 않아 서비스가 요청을 거부했습니다. | 업적 ID와 타이틀의 구성을 확인하세요. 같은 요청을 다시 시도하면 같은 방식으로 실패합니다. |
| `E_INVALIDARG` | 컨텍스트, 업적 ID 또는 비동기 블록이 null입니다. | 인수를 확인하세요. `percentComplete`에 1에서 100 사이의 값을 전달하세요. |
| `E_XBL_NOT_INITIALIZED` | XSAPI가 초기화되지 않았습니다. | 업적을 업데이트하기 전에 `XblInitialize`를 호출하세요. |

[이 항목의 맨 위로 돌아가기.](#top)


## Related topics

- [타이틀 관리 업적 예제 코드(목차)](https://docs.xbox.com/ko/services/xbox-services/player-data/achievements/title-managed/how-to/live-achievements-howto-nav.md)
- [타이틀 관리 업적 예제](https://docs.xbox.com/ko/services/xbox-services/player-data/achievements/title-managed/how-to/index.md)
- [통계와 업적](https://docs.xbox.com/ko/build/steam-porting-guide/features/stats-and-achievements.md)
- [PC용 Unreal 개발: 시작하기(이전 버전)](https://docs.xbox.com/ko/build/gdk-and-engines/unreal/unreal-legacy.md)
- [이벤트 기반 대 타이틀 관리 업적](https://docs.xbox.com/ko/services/xbox-services/player-data/achievements/live-achievements-eb-vs-tm.md)
