> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Experience SDK for Game Engine API 레퍼런스

게임 엔진용 GS2-Experience SDK의 모델 사양과 API 레퍼런스



## 모델

### EzStatus

스테이터스<br>

스테이터스란 프로퍼티ID마다 존재하는 엔티티로,<br>
현재의 경험치와 랭크 캡 값을 보유합니다.<br>

프로퍼티ID란 스테이터스 고유의 ID로, 개발자가 임의의 값을 설정할 수 있습니다.<br>
GS2에서는 경험치를 보유한 GS2-Inventory의 아이템 세트GRN이나 GS2-Dictionary의 엔트리GRN 뒤에<br>
경험치 모델이 되는 접미사를 추가한 값을 프로퍼티ID로 사용할 것을 권장합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| experienceName | string |  | ✓ |  |  ~ 128자 | 경험치 모델 이름<br>이 스테이터스의 랭킹 규칙을 정의하는 경험치 모델의 이름입니다. 어떤 랭크업 임계값 테이블과 랭크 캡 설정이 적용되는지를 결정합니다. |
| propertyId | string |  | ✓ |  |  ~ 1024자 | 프로퍼티ID<br>사용자 스코프 내에서 이 스테이터스를 고유하게 식별하는 개발자 정의 식별자입니다. 경험치를 보유한 GS2-Inventory의 아이템 세트 GRN이나 GS2-Dictionary의 엔트리 GRN 끝에 경험치 모델의 접미사를 붙인 값을 사용할 것을 권장합니다. |
| experienceValue | long |  |  | 0 | 0 ~ 9223372036854775805 | 누적 획득 경험치<br>이 스테이터스가 축적한 총 경험치입니다. 현재 랭크는 이 값으로부터 랭크업 임계값 테이블을 사용하여 산출됩니다. 현재 랭크 캡에 대응하는 임계값을 초과하여 경험치를 획득할 수 없습니다. |
| rankValue | long |  |  | 0 | 0 ~ 9223372036854775805 | 현재 랭크<br>랭크업 임계값 테이블을 사용하여 누적 경험치로부터 산출되는 랭크(레벨)입니다. 0부터 시작하며 경험치 임계값을 초과할 때마다 증가합니다. 현재 랭크 캡 값을 초과할 수 없습니다. |
| rankCapValue | long |  | ✓ |  | 0 ~ 9223372036854775805 | 현재 랭크 캡<br>이 스테이터스가 현재 도달할 수 있는 최대 랭크입니다. 초기값은 경험치 모델의 defaultRankCap으로 설정되며, 한계돌파 등의 랭크 캡 증가 조작을 통해 maxRankCap까지 끌어올릴 수 있습니다. |
| nextRankUpExperienceValue | long |  |  | 0 | 0 ~ 9223372036854775805 | 다음 랭크업에 필요한 경험치량<br>다음 랭크에 도달하기 위해 필요한 누적 경험치의 임계값입니다. 스테이터스가 이미 랭크 캡에 도달한 경우 0을 반환합니다. 게임 UI에서 프로그레스 바나 남은 경험치를 표시하는 데 유용합니다. |

**관련 메서드:**
getStatus - 특정 아이템이나 캐릭터의 레벨·경험치 상태를 조회하기
getStatusWithSignature - 위변조 방지 서명과 함께 레벨·경험치 상태를 조회하기
listStatuses - 플레이어의 레벨·경험치 상태 목록을 조회하기


---

### EzExperienceModel

경험치 모델<br>

경험치와 랭크 시스템의 규칙을 정의합니다. 랭크업에 필요한 경험치의 임계값, 기본 랭크 캡, 최대 랭크 캡을 설정합니다. 랭크 캡은 스테이터스가 도달할 수 있는 최대 랭크를 제한하며, 스테이터스별로 최대 랭크 캡까지 인상할 수 있습니다(예: 한계돌파). 옵션으로 현재 랭크에 따라 보상 배율을 조정하는 입수 액션 레이트 테이블을 포함할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 경험치 모델 이름<br>경험치 모델 고유 이름. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| defaultExperience | long |  |  | 0 | 0 ~ 9223372036854775805 | 경험치 초기값<br>신규 생성된 스테이터스에 할당되는 경험치입니다. 일반적으로 플레이어가 진행의 처음부터 시작하도록 0으로 설정됩니다. 초기 랭크는 이 값으로부터 랭크업 임계값 테이블을 사용하여 결정됩니다. |
| defaultRankCap | long |  | ✓ |  | 0 ~ 9223372036854775805 | 랭크 캡 초기값<br>신규 생성된 스테이터스가 도달할 수 있는 기본 최대 랭크입니다. 이 랭크의 임계값을 초과한 경험치는 폐기되거나 오버플로 스크립트가 트리거됩니다. 랭크 캡은 한계돌파 등의 조작을 통해 스테이터스별로 maxRankCap까지 인상할 수 있습니다. |
| maxRankCap | long |  | ✓ |  | 0 ~ 9223372036854775805 | 랭크 캡의 최댓값<br>랭크 캡의 절대적인 상한입니다. 랭크 캡 증가 조작(한계돌파 등)을 수행하더라도 랭크 캡은 이 값을 초과할 수 없습니다. defaultRankCap 이상의 값이어야 합니다. |
| rankThreshold | [EzThreshold](#ezthreshold) |  | ✓ |  |  | 랭크업 임계값<br>각 랭크에 필요한 누적 경험치를 정의하는 임계값 테이블을 참조합니다. 임계값의 엔트리 수가 도달 가능한 최대 랭크를 결정하며, 각 엔트리의 값은 다음 랭크에 도달하는 데 필요한 경험치를 지정합니다. |
| acquireActionRates | [List&lt;EzAcquireActionRate&gt;](#ezacquireactionrate) |  |  |  | 0 ~ 100 items | 보상 가산 테이블 목록<br>스테이터스의 랭크를 참조로 사용할 때 보상량을 조정하는 랭크 기반 배율 테이블을 정의합니다. 각 테이블은 랭크와 배율을 매핑하여, 동일한 액션에서도 더 높은 랭크의 캐릭터가 더 많은 보상을 받는 구조를 구현할 수 있습니다. |

**관련 메서드:**
getExperienceModel - 이름을 지정하여 경험치 모델을 조회하기
listExperienceModels - 경험치 모델 목록 조회하기


---

### EzThreshold

랭크업 임계값<br>

랭크업 임계값은 경험치로부터 랭크(레벨)를 결정하는 데 필요한 수열입니다.<br>
[10, 20]이라는 값을 설정한 경우, 경험치 값이 0~9 사이면 랭크1, 10~19 사이면 랭크2, 경험치 값이 20이면 랭크3이 되며, 그 이상 경험치를 획득할 수 없게 됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| values | List&lt;long&gt; |  | ✓ |  | 1 ~ 10000 items | 랭크업 경험치 임계값 목록<br>랭크 진행을 정의하는 누적 경험치의 순서가 있는 배열입니다. 항목 수가 도달 가능한 최대 랭크를 결정합니다. 예를 들어 [10, 20]인 경우, 경험치 0~9에서 랭크1, 10~19에서 랭크2, 20 이상에서 랭크3(그 이상의 경험치 획득은 불가)이 됩니다. |


**관련 모델:**
EzExperienceModel - 경험치 모델



---

### EzAcquireAction

입수 액션

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 입수 액션에서 실행할 액션의 종류 |
| request | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |


---

### EzAcquireActionRate

보상 가산 테이블<br>

상태의 현재 랭크에 따라 보상량을 조정하는 랭크 기반 배율 테이블을 정의합니다. 테이블의 각 항목은 랭크에 대응하며, 입수량에 적용되는 배율을 지정합니다. 표준적인 배정밀도 부동소수점 값과, 대규모 계산용 대수 문자열 표현을 모두 지원합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 보상 가산 테이블 이름<br>이 보상 가산 테이블의 고유 식별자입니다. 특정 입수 액션에 적용할 배율 테이블을 지정할 때 참조됩니다. |
| mode | 문자열 열거형<br>enum {<br>"double",<br>"big"<br>}<br> |  |  | "double" |  | 보상 가산 테이블의 종류<br>배율 값의 수치 정밀도를 선택합니다. 표준적인 부동소수점 수(2^48까지)에는 "double"을, 대규모 계산이 필요한 경우에는 1024자리까지의 문자열 표현을 지원하는 "big"을 사용합니다.double: 2^48 미만의 부동소수점 수 / big: 문자열 표기로 1024자리 미만의 부동소수점 수 /  |
| rates | List&lt;double&gt; | {mode} == "double" | ✓※ |  | 1 ~ 10000 items | 랭크별 가산량(배율)<br>랭크를 인덱스로 하는 배율 값의 배열입니다. i번째 엔트리는 스테이터스가 랭크 i일 때 적용되는 보상 배율을 정의합니다. mode가 "double"로 설정된 경우에 사용됩니다.<br><br>※ mode이(가) "double" 이면 필수 |
| bigRates | List&lt;string&gt; | {mode} == "big" | ✓※ |  | 1 ~ 10000 items | 랭크별 가산량(배율)<br>랭크를 인덱스로 하는 문자열 표현 배율 값의 배열입니다. i번째 엔트리는 스테이터스가 랭크 i일 때 적용되는 보상 배율을 정의합니다. 대수치 정밀도가 필요한 계산에서 mode가 "big"으로 설정된 경우에 사용됩니다.<br><br>※ mode이(가) "big" 이면 필수 |


**관련 모델:**
EzExperienceModel - 경험치 모델



---

### EzVerifyActionResult

검증 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 검증 액션에서 실행할 액션의 종류 |
| verifyRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| verifyResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzConsumeActionResult

소비 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 소비 액션에서 실행할 액션의 종류 |
| consumeRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| consumeResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzAcquireActionResult

획득 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 입수 액션에서 실행할 액션의 종류 |
| acquireRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| acquireResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzTransactionResult

트랜잭션 실행 결과<br>

서버 사이드에서 트랜잭션 자동 실행 기능을 이용하여 실행된 트랜잭션의 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| transactionId | string |  | ✓ |  | 36 ~ 36자 | 트랜잭션 ID |
| verifyResults | [List&lt;EzVerifyActionResult&gt;](#ezverifyactionresult) |  |  |  | 0 ~ 10 items | 검증 액션의 실행 결과 목록 |
| consumeResults | [List&lt;EzConsumeActionResult&gt;](#ezconsumeactionresult) |  |  | [] | 0 ~ 10 items | 소비 액션의 실행 결과 목록 |
| acquireResults | [List&lt;EzAcquireActionResult&gt;](#ezacquireactionresult) |  |  | [] | 0 ~ 100 items | 획득 액션 실행 결과 리스트 |


---

## 메서드

### getExperienceModel

이름을 지정하여 경험치 모델을 조회하기<br>

이름을 지정하여 경험치 모델을 1건 조회합니다.<br>
조회할 수 있는 정보에는 각 레벨에 필요한 경험치(랭크업 임계값), 기본 최대 레벨, 절대 최대 레벨이 포함됩니다.<br>
레벨 진행도를 계산·표시할 때 사용합니다. 예를 들어, 플레이어의 무기가 다음 레벨에 도달하는 데 앞으로 얼마나 경험치가 필요한지, 한계 돌파 후 최대 레벨은 몇인지를 표시하는 데 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| experienceName | string |  | ✓|  |  ~ 128자 | 경험치 모델 이름<br>경험치 모델 고유 이름. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzExperienceModel](#ezexperiencemodel) | 경험치 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).ExperienceModel(
        experienceName: "experience-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).ExperienceModel(
        experienceName: "experience-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->ExperienceModel(
        "experience-0001" // experienceName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.experience.namespace_(
        "namespace-0001"
    ).experience_model(
        "experience-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).ExperienceModel(
        experienceName: "experience-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).ExperienceModel(
        experienceName: "experience-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->ExperienceModel(
        "experience-0001" // experienceName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Experience::Model::FExperienceModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.experience.namespace_(
        "namespace-0001"
    ).experience_model(
        "experience-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listExperienceModels

경험치 모델 목록 조회하기<br>

이 네임스페이스에 등록된 모든 경험치 모델을 조회합니다.<br>
경험치 모델은 레벨업 시스템을 정의합니다. 각 레벨에 필요한 경험치, 기본 최대 레벨, 절대 최대 레벨 등을 설정합니다.<br>
레벨업 관련 UI를 구성할 때 사용합니다. 예를 들어 "다음 레벨까지: 150/500 EXP" 표시나, 캐릭터 상세 화면에서 레벨업 임계값을 표시하는 데 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzExperienceModel&gt;](#ezexperiencemodel) | 경험치 모델 목록|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.ExperienceModelsAsync(
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.ExperienceModels(
    );
    List<EzExperienceModel> items = new List<EzExperienceModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->ExperienceModels(
    );
    TArray<Gs2::UE5::Experience::Model::FEzExperienceModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeExperienceModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeExperienceModels(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeExperienceModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeExperienceModels(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeExperienceModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeExperienceModels(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### getStatus

특정 아이템이나 캐릭터의 레벨·경험치 상태를 조회하기<br>

플레이어가 보유한 특정 프로퍼티의 현재 레벨, 경험치, 최대 레벨을 조회합니다.<br>
프로퍼티는 경험치 모델 이름(어떤 레벨업 시스템을 사용하는지)과 프로퍼티 ID(어떤 아이템이나 캐릭터인지)로 식별합니다.<br>
상세 화면을 표시할 때 사용합니다. 예를 들어 "철검 Lv.15 — EXP: 3200/5000 — 최대 Lv: 50"과 같은 표시에 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| experienceName | string |  | ✓|  |  ~ 128자 | 경험치 모델 이름<br>이 스테이터스의 랭킹 규칙을 정의하는 경험치 모델의 이름입니다. 어떤 랭크업 임계값 테이블과 랭크 캡 설정이 적용되는지를 결정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| propertyId | string |  | ✓|  |  ~ 1024자 | 프로퍼티ID<br>사용자 스코프 내에서 이 스테이터스를 고유하게 식별하는 개발자 정의 식별자입니다. 경험치를 보유한 GS2-Inventory의 아이템 세트 GRN이나 GS2-Dictionary의 엔트리 GRN 끝에 경험치 모델의 접미사를 붙인 값을 사용할 것을 권장합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzStatus](#ezstatus) | 상태|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "character_ssr", // experienceName
        "property-0001" // propertyId
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.experience.namespace_(
        "namespace-0001"
    ).me(game_session).status(
        "character_ssr",
        "property-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "character_ssr", // experienceName
        "property-0001" // propertyId
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Experience::Model::FStatus> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.experience.namespace_(
        "namespace-0001"
    ).me(game_session).status(
        "character_ssr",
        "property-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### getStatusWithSignature

위변조 방지 서명과 함께 레벨·경험치 상태를 조회하기<br>

getStatus와 동일한 레벨·경험치 정보를 조회하지만, 데이터가 변조되지 않았음을 증명하는 암호 서명도 함께 반환합니다.<br>
플레이어의 레벨을 신뢰할 수 있는 방식으로 검증해야 하는 경우에 유용합니다. 예를 들어, 다른 서비스에서 레벨을 조건으로 사용하는 경우나, 외부 시스템에 레벨 데이터를 전달하여 진위를 확인해야 하는 경우에 사용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| experienceName | string |  | ✓|  |  ~ 128자 | 경험치 모델 이름<br>이 스테이터스의 랭킹 규칙을 정의하는 경험치 모델의 이름입니다. 어떤 랭크업 임계값 테이블과 랭크 캡 설정이 적용되는지를 결정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| propertyId | string |  | ✓|  |  ~ 1024자 | 프로퍼티ID<br>사용자 스코프 내에서 이 스테이터스를 고유하게 식별하는 개발자 정의 식별자입니다. 경험치를 보유한 GS2-Inventory의 아이템 세트 GRN이나 GS2-Dictionary의 엔트리 GRN 끝에 경험치 모델의 접미사를 붙인 값을 사용할 것을 권장합니다. |
| keyId | string |  | | "grn:gs2:{region}:{ownerId}:key:default:key:default" |  ~ 1024자 | 암호화 키 GRN |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzStatus](#ezstatus) | 상태|
| body | string | 검증 대상 오브젝트|
| signature | string | 서명|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    var result = await domain.GetStatusWithSignatureAsync(
        keyId: "key-0001"
    );
    var item = await result.ModelAsync();
    var body = result.Body;
    var signature = result.Signature;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        experienceName: "character_ssr",
        propertyId: "property-0001"
    );
    var future = domain.GetStatusWithSignatureFuture(
        keyId: "key-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var body = future.Result.Body;
    var signature = future.Result.Signature;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "character_ssr", // experienceName
        "property-0001" // propertyId
    );
    const auto Future = Domain->GetStatusWithSignature(
        "key-0001" // keyId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto Body = Result->Body;
    const auto Signature = Result->Signature;

```

**Godot**
```gdscript

var domain = ez.experience.namespace_(
        "namespace-0001"
    ).me(game_session).status(
        "character_ssr",
        "property-0001"
    )

var async_result = await domain.get_status_with_signature(
    "key-0001" # key_id
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### listStatuses

플레이어의 레벨·경험치 상태 목록을 조회하기<br>

플레이어가 보유한 아이템이나 캐릭터의 현재 레벨과 경험치 정보를 조회합니다.<br>
경험치 모델 이름으로 필터링할 수도 있습니다. 생략하면 모든 경험치 타입의 상태가 반환됩니다.<br>
각 상태에는 특정 프로퍼티(무기나 캐릭터 등)의 현재 경험치, 현재 레벨, 최대 레벨이 포함됩니다.<br>
플레이어가 레벨을 올린 아이템의 목록 화면을 구성하는 데 사용합니다. 예를 들어 "철검 Lv.15, 불의 지팡이 Lv.8"처럼 표시할 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| experienceName | string |  | |  |  ~ 128자 | 경험치 모델명 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| pageToken | string |  | |  |  ~ 1024자 | 데이터 취득을 시작할 위치를 지정하는 토큰 |
| limit | int |  | | 30 | 1 ~ 1000 | 취득할 데이터 건수 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzStatus&gt;](#ezstatus) | 상태 목록|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.StatusesAsync(
        experienceName: "character_ssr"
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Statuses(
        experienceName: "character_ssr"
    );
    List<EzStatus> items = new List<EzStatus>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Statuses(
        "character_ssr" // experienceName
    );
    TArray<Gs2::UE5::Experience::Model::FEzStatusPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeStatuses(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeStatuses(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Experience.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeStatuses(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeStatuses(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Experience->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeStatuses(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeStatuses(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---



