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

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

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



## 모델

### EzStampSheetResult

트랜잭션 실행 결과(레거시)<br>

서버사이드 자동 실행으로 처리된 트랜잭션의 실행 결과를 기록합니다.<br>
각 단계의 요청 내용과 응답 결과를 포함합니다: 검증 액션(사전 조건 확인), 소비 액션, 입수 액션. 오류 감지 및 재시도 로직을 위해 HTTP 상태 코드도 추적합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| transactionId | string |  | ✓ |  | 36 ~ 36자 | 트랜잭션 ID<br>이 트랜잭션을 고유하게 식별하는 UUID입니다. 트랜잭션과 그 실행 결과, 그리고 연쇄되는 후속 트랜잭션의 연결에 사용됩니다. |
| taskRequests | [List&lt;EzConsumeAction&gt;](#ezconsumeaction) |  |  |  | 0 ~ 100 items | 소비 액션의 요청 내용 목록 |
| sheetRequest | [EzAcquireAction](#ezacquireaction) |  | ✓ |  |  | 입수 액션의 요청 내용 |
| taskResults | List&lt;string&gt; |  |  | [] | 0 ~ 100 items | 소비 액션의 실행 결과 |
| sheetResult | string |  |  |  |  ~ 1048576자 | 입수 액션의 실행 결과 응답 내용 |

**관련 메서드:**
getStampSheetResult - 완료된 트랜잭션의 결과를 취득한다(레거시)


---

### EzTransactionResult

트랜잭션 실행 결과<br>

서버사이드 자동 실행으로 처리된 분산 트랜잭션의 실행 결과를 기록합니다.<br>
각 단계의 구조화된 결과를 포함합니다: 검증 액션(사전 조건 확인), 소비 액션(리소스 소비), 입수 액션(리소스 지급). 각 액션 결과에는 요청, HTTP 상태 코드, 응답 페이로드가 포함됩니다. 상태 코드(비2xx)에 의한 오류 감지와, 충돌(409)이나 서버 오류(5xx)에서의 재시도가 지원됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| transactionId | string |  | ✓ |  | 36 ~ 36자 | 트랜잭션 ID<br>이 분산 트랜잭션을 고유하게 식별하는 UUID입니다. 실행 결과 조회 및 원래 API 요청과의 연결에 사용됩니다. |
| verifyResults | [List&lt;EzVerifyActionResult&gt;](#ezverifyactionresult) |  |  |  | 0 ~ 100 items | 검증 액션의 실행 결과 목록 |
| consumeResults | [List&lt;EzConsumeActionResult&gt;](#ezconsumeactionresult) |  |  |  | 0 ~ 100 items | 소비 액션의 실행 결과 목록 |
| acquireResults | [List&lt;EzAcquireActionResult&gt;](#ezacquireactionresult) |  |  |  | 0 ~ 100 items | 입수 액션의 실행 결과 목록 |

**관련 메서드:**
getTransactionResult - 완료된 트랜잭션의 결과를 취득한다


---

### EzDistributorModel

배포 모델<br>

배포 모델이란 리소스 입수 시 소지 한도를 초과하여 입수했을 때의 정책을 설정하는 엔티티입니다.<br>
GS2-Distributor를 통해 입수 처리를 수행함으로써, 넘친 리소스를 GS2-Inbox의 메시지로 전송할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 배포 모델 이름<br>배포 모델 고유의 이름. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| inboxNamespaceId | string |  |  |  |  ~ 1024자 | 넘친 리소스를 전송할 GS2-Inbox 네임스페이스 GRN<br>리소스 입수가 플레이어의 소지 한도를 초과한 경우, 넘친 리소스는 지정된 GS2-Inbox 네임스페이스에 메시지로 전송됩니다. 플레이어는 이후 수신함에서 리소스를 수령할 수 있습니다. |
| whiteListTargetIds | List&lt;string&gt; |  |  | [] | 0 ~ 1000 items | GS2-Distributor를 통해 처리할 수 있는 대상 리소스 GRN의 화이트리스트<br>이 배포 모델을 사용하여 입수 처리를 수행할 수 있는 대상 리소스의 GRN 프리픽스를 지정합니다. |

**관련 메서드:**
getDistributorModel - 이름을 지정하여 배포 모델 정의를 취득한다
listDistributorModels - 배포 모델 정의 목록을 취득한다


---

### EzConfig

컨피그 설정<br>

트랜잭션의 변수에 적용하는 설정 값

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| key | string |  | ✓ |  |  ~ 64자 | 이름 |
| value | string |  |  |  |  ~ 51200자 | 값 |

**관련 메서드:**
setDefaultConfig - 트랜잭션의 기본 설정값을 등록한다


---

### EzDistributeResource

리소스 배포<br>

입수 액션과 그 요청 파라미터로 구성된 단일 리소스 배포 조작을 나타냅니다. 플레이어에게 리소스를 배포할 때 어떤 GS2 API 액션을 어떤 파라미터로 실행할지 지정하는 데 사용됩니다.

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


---

### EzBatchRequestPayload

API 일괄 실행 요청<br>

일괄 실행 내 단일 API 요청을 나타냅니다. 여러 배치 요청 페이로드를 함께 전송함으로써 여러 GS2 API 호출을 한 번의 라운드트립으로 실행할 수 있어, 네트워크 오버헤드와 지연 시간을 줄일 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| requestId | string |  | ✓ |  |  ~ 128자 | 요청 ID<br>배치 내에서 이 요청에 대해 클라이언트가 할당한 식별자입니다. 배치 응답 내에서 각 요청과 대응하는 결과를 연결하는 데 사용됩니다. |
| service | 문자열 열거형<br>enum {<br>"account",<br>"adReward",<br>"auth",<br>"buff",<br>"chat",<br>"datastore",<br>"deploy",<br>"dictionary",<br>"distributor",<br>"enchant",<br>"enhance",<br>"exchange",<br>"experience",<br>"formation",<br>"friend",<br>"gateway",<br>"grade",<br>"guard",<br>"guild",<br>"identifier",<br>"idle",<br>"inbox",<br>"inventory",<br>"jobQueue",<br>"key",<br>"limit",<br>"lock",<br>"log",<br>"loginReward",<br>"lottery",<br>"matchmaking",<br>"megaField",<br>"mission",<br>"money",<br>"money2",<br>"news",<br>"quest",<br>"ranking",<br>"ranking2",<br>"realtime",<br>"schedule",<br>"script",<br>"seasonRating",<br>"serialKey",<br>"showcase",<br>"skillTree",<br>"stamina",<br>"stateMachine",<br>"version"<br>}<br> |  | ✓ |  |  | 마이크로서비스 이름<br>호출할 GS2 마이크로서비스 이름입니다(예: "inventory", "experience", "money"). 이 API 요청을 수신할 서비스 엔드포인트를 결정합니다.account: GS2-Account / adReward: GS2-AdReward / auth: GS2-Auth / buff: GS2-Buff / chat: GS2-Chat / datastore: GS2-Datastore / deploy: GS2-Deploy / dictionary: GS2-Dictionary / distributor: GS2-Distributor / enchant: GS2-Enchant / enhance: GS2-Enhance / exchange: GS2-Exchange / experience: GS2-Experience / formation: GS2-Formation / friend: GS2-Friend / gateway: GS2-Gateway / grade: GS2-Grade / guard: GS2-Guard / guild: GS2-Guild / identifier: GS2-Identifier / idle: GS2-Idle / inbox: GS2-Inbox / inventory: GS2-Inventory / jobQueue: GS2-JobQueue / key: GS2-Key / limit: GS2-Limit / lock: GS2-Lock / log: GS2-Log / loginReward: GS2-LoginReward / lottery: GS2-Lottery / matchmaking: GS2-Matchmaking / megaField: GS2-MegaField / mission: GS2-Mission / money: GS2-Money / money2: GS2-Money2 / news: GS2-News / quest: GS2-Quest / ranking: GS2-Ranking / ranking2: GS2-Ranking2 / realtime: GS2-Realtime / schedule: GS2-Schedule / script: GS2-Script / seasonRating: GS2-SeasonRating / serialKey: GS2-SerialKey / showcase: GS2-Showcase / skillTree: GS2-SkillTree / stamina: GS2-Stamina / stateMachine: GS2-StateMachine / version: GS2-Version /  |
| methodName | string |  | ✓ |  |  ~ 128자 | 메서드 이름<br>대상 서비스에서 호출할 API 메서드 이름입니다(예: "describeNamespaces", "getInventory"). 지정된 서비스의 유효한 API 메서드와 일치해야 합니다. |
| parameter | string |  | ✓ |  |  ~ 10240자 | 파라미터<br>API 메서드의 JSON으로 직렬화된 요청 파라미터입니다. 지정된 서비스 메서드의 요청 스키마를 준수해야 합니다. |

**관련 메서드:**
batchExecuteApi - 여러 API 호출을 일괄 실행한다


---

### EzBatchResultPayload

API 일괄 실행 결과<br>

일괄 실행 내 단일 API 요청의 결과를 나타냅니다. 각 결과는 요청 ID로 원래 요청과 연결되며, HTTP 상태 코드와 JSON 응답 페이로드를 포함합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| requestId | string |  | ✓ |  |  ~ 128자 | 요청 ID<br>대응하는 배치 요청과 일치하는 클라이언트 할당 식별자입니다. 이 결과를 원래 요청과 연결하는 데 사용됩니다. |
| statusCode | int |  | ✓ |  | 100 ~ 1000 | 상태 코드<br>이 배치 요청에 대해 GS2 API가 반환한 HTTP 상태 코드입니다. 2xx는 성공, 4xx는 클라이언트 오류, 5xx는 서버 오류를 나타냅니다. |
| resultPayload | string |  | ✓ |  |  ~ 10240자 | 응답<br>이 배치 요청에 대해 GS2 API가 반환한 JSON 응답 본문입니다. API 메서드의 응답 데이터 또는 오류 상세 정보를 포함합니다. |

**관련 메서드:**
batchExecuteApi - 여러 API 호출을 일괄 실행한다


---

### EzAcquireAction

입수 액션<br>

분산 트랜잭션 내 리소스 입수 조작을 나타냅니다. 플레이어에게 리소스(아이템, 화폐, 경험치 등)를 지급하는 입수 액션에 대응합니다. GS2 API의 액션 식별자와 JSON으로 직렬화된 요청 파라미터를 포함합니다.

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


**관련 모델:**
EzStampSheetResult - 트랜잭션 실행 결과(레거시)



---

### EzConsumeAction

소비 액션<br>

분산 트랜잭션 내 리소스 소비 조작을 나타냅니다. 플레이어로부터 리소스(아이템, 화폐, 스태미나 등)를 소비하는 소비 액션에 대응합니다. 소비 액션은 입수 액션보다 먼저 실행되어, 플레이어가 필요한 비용을 충족하는지 확인합니다.

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


**관련 모델:**
EzStampSheetResult - 트랜잭션 실행 결과(레거시)



---

### EzVerifyAction

검증 액션<br>

분산 트랜잭션 내 사전 조건 검증 조작을 나타냅니다. 소비·입수 액션보다 먼저 실행되어 조건이 충족되었는지 검증합니다(예: 소지 한도 확인, 퀘스트 완료 상태 검증 등). 검증 액션 중 하나라도 실패하면 트랜잭션 전체가 중단됩니다.

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


---

### EzAcquireActionResult

획득 액션 실행 결과<br>

단일 획득 액션 실행 결과를 기록합니다. 원본 요청, 성공·실패를 나타내는 HTTP 상태 코드, GS2 API로부터의 JSON 응답 페이로드를 포함합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| acquireRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드<br>이 입수 액션에 대해 GS2 API가 반환한 HTTP 상태 코드입니다. 2xx는 성공, 409는 재시도가 필요한 충돌, 5xx는 서버 오류를 나타냅니다. |
| acquireResult | string |  |  |  |  ~ 1048576자 | 결과 내용<br>입수 액션 실행 후 GS2 API가 반환한 JSON 응답 본문입니다. 입수한 리소스의 상세 정보를 포함하며, 연쇄되는 트랜잭션 ID가 포함될 수도 있습니다. |


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



---

### EzConsumeActionResult

소비 액션 실행 결과<br>

단일 소비 액션 실행 결과를 기록합니다. 원본 요청, 성공·실패를 나타내는 HTTP 상태 코드, GS2 API로부터의 JSON 응답 페이로드를 포함합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| consumeRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드<br>이 소비 액션에 대해 GS2 API가 반환한 HTTP 상태 코드입니다. 2xx는 성공, 409는 재시도가 필요한 충돌, 5xx는 서버 오류를 나타냅니다. |
| consumeResult | string |  |  |  |  ~ 1048576자 | 결과 내용<br>소비 액션 실행 후 GS2 API가 반환한 JSON 응답 본문입니다. 소비된 리소스의 상세 정보를 포함합니다. |


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



---

### EzVerifyActionResult

검증 액션 실행 결과<br>

단일 검증 액션 실행 결과를 기록합니다. 원본 요청, 성공·실패를 나타내는 HTTP 상태 코드, GS2 API로부터의 JSON 응답 페이로드를 포함합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| verifyRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드<br>이 검증 액션에 대해 GS2 API가 반환한 HTTP 상태 코드입니다. 2xx는 검증 성공, 비2xx는 사전 조건이 충족되지 않았음을 나타냅니다. |
| verifyResult | string |  |  |  |  ~ 1048576자 | 결과 내용<br>검증 액션 실행 후 GS2 API가 반환한 JSON 응답 본문입니다. 검증 결과의 상세 정보를 포함합니다. |


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



---

## 메서드

### getDistributorModel

이름을 지정하여 배포 모델 정의를 취득한다<br>

이름을 지정하여 배포 모델을 1건 취득합니다.<br>
취득할 수 있는 정보에는 허용된 서비스 액션과, 오버플로 처리용으로 설정된 인박스 네임스페이스가 포함됩니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzDistributorModel](#ezdistributormodel) | 배포 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).DistributorModel(
        distributorName: "distributor-model-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).DistributorModel(
        distributorName: "distributor-model-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->DistributorModel(
        "distributor-model-0001" // distributorName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).distributor_model(
        "distributor-model-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.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).DistributorModel(
        distributorName: "distributor-model-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

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

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

```

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

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

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).distributor_model(
        "distributor-model-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의 실행에 의해 변화한 것만이 대상이 됩니다.

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

---

### listDistributorModels

배포 모델 정의 목록을 취득한다<br>

이 네임스페이스에 등록되어 있는 모든 배포 모델을 취득합니다.<br>
배포 모델은 리소스 배포 규칙을 정의합니다. 허용할 서비스 액션이나, 플레이어의 인벤토리가 가득 찼을 때 넘친 아이템을 어디로 보낼지(예: 선물 상자 / 인박스)를 설정합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzDistributorModel&gt;](#ezdistributormodel) | 배포 모델 목록|

#### 구현 예제




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

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.DistributorModels(
    );
    List<EzDistributorModel> items = new List<EzDistributorModel>();
    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->Distributor->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->DistributorModels(
    );
    TArray<Gs2::UE5::Distributor::Model::FEzDistributorModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### batchExecuteApi

여러 API 호출을 일괄 실행한다<br>

여러 GS2 API 요청을 1회의 호출로 한꺼번에 전송하고, 응답을 한꺼번에 받습니다.<br>
통신 왕복 횟수가 줄어들어, 여러 API를 동시에 호출해야 하는 상황에서 성능이 향상됩니다.<br>
예를 들어, 플레이어가 홈 화면을 열었을 때 인벤토리·스태미나·퀘스트 진행 상황을 한꺼번에 취득하는 경우 등에 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| requestPayloads | [List&lt;EzBatchRequestPayload&gt;](#ezbatchrequestpayload) |  | ✓|  | 1 ~ 100 items | 배치 요청 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| results | [List&lt;EzBatchResultPayload&gt;](#ezbatchresultpayload) | 배치 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: null
    );
    var result = await domain.BatchExecuteApiAsync(
        requestPayloads: new List<Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload> {
            new Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload() {
                Service = "inventory",
                MethodName = "describeSimpleItems",
                Parameter = "{\"namespaceName\": \"namespace-0001\", \"inventoryName\": \"inventory-0001\", \"accessToken\": \"accessToken-0001\"}",
            },
            new Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload() {
                Service = "exchange",
                MethodName = "describeRateModels",
                Parameter = "{\"namespaceName\": \"namespace-0001\"}",
            },
        }
    );
    var results = result.Results;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: null
    );
    var future = domain.BatchExecuteApiFuture(
        requestPayloads: new List<Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload> {
            new Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload() {
                Service = "inventory",
                MethodName = "describeSimpleItems",
                Parameter = "{\"namespaceName\": \"namespace-0001\", \"inventoryName\": \"inventory-0001\", \"accessToken\": \"accessToken-0001\"}",
            },
            new Gs2.Unity.Gs2Distributor.Model.EzBatchRequestPayload() {
                Service = "exchange",
                MethodName = "describeRateModels",
                Parameter = "{\"namespaceName\": \"namespace-0001\"}",
            },
        }
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var results = future.Result.Results;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        nullptr // namespaceName
    );
    const auto Future = Domain->BatchExecuteApi(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Distributor::Model::FEzBatchRequestPayload>>>();
            v->Add(
                MakeShared<Gs2::UE5::Distributor::Model::FEzBatchRequestPayload>()
                ->WithService(TOptional<FString>("inventory"))
                ->WithMethodName(TOptional<FString>("describeSimpleItems"))
                ->WithParameter(TOptional<FString>("{\"namespaceName\": \"namespace-0001\", \"inventoryName\": \"inventory-0001\", \"accessToken\": \"accessToken-0001\"}"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Distributor::Model::FEzBatchRequestPayload>()
                ->WithService(TOptional<FString>("exchange"))
                ->WithMethodName(TOptional<FString>("describeRateModels"))
                ->WithParameter(TOptional<FString>("{\"namespaceName\": \"namespace-0001\"}"))
            );
            return v;
        }() // requestPayloads
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();
    const auto Results = Result->Results;

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        null
    )

var async_result = await domain.batch_execute_api(
    [
        Gs2DistributorEzBatchRequestPayload.new()
            .with_service("inventory")
            .with_method_name("describeSimpleItems")
            .with_parameter("{\"namespaceName\": \"namespace-0001\", \"inventoryName\": \"inventory-0001\", \"accessToken\": \"accessToken-0001\"}"),
        Gs2DistributorEzBatchRequestPayload.new()
            .with_service("exchange")
            .with_method_name("describeRateModels")
            .with_parameter("{\"namespaceName\": \"namespace-0001\"}"),
    ] # request_payloads
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### freezeMasterData

현재 시점의 마스터 데이터를 고정한다<br>

현재 마스터 데이터의 스냅샷을 생성하여, 이후 트랜잭션이 이 고정된 버전을 사용하도록 합니다. 마스터 데이터가 나중에 갱신되어도 영향을 받지 않습니다.<br>
정합성을 유지하는 데 유용합니다. 예를 들어, 플레이어가 퀘스트를 시작한 경우 보상은 클리어 시점이 아니라 시작 시점의 마스터 데이터에 기반해야 합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| newContextStack | string | 마스터 데이터를 고정하는 시각을 기록한 컨텍스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Distribute(
    );
    var result = await domain.FreezeMasterDataAsync(
        accessToken: null
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Distribute(
    );
    var future = domain.FreezeMasterDataFuture(
        accessToken: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Distribute(
    );
    const auto Future = Domain->FreezeMasterData(
        nullptr // accessToken
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```


---

### freezeMasterDataBySignedTimestamp

서명된 타임스탬프 시점에 마스터 데이터를 고정한다<br>

서명된 타임스탬프를 사용하여 특정 시점의 마스터 데이터를 고정합니다.<br>
FreezeMasterData('지금' 시점에서 고정)와 달리, 정확한 시각을 지정할 수 있습니다. 고정할 시점이 서버 측에서 미리 정해져 있는 경우 등에 사용합니다.<br>
서명된 타임스탬프는 SignFreezeMasterDataTimestamp로 발행할 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| body | string |  | ✓|  |  ~ 1024자 | 본문 |
| signature | string |  | ✓|  |  ~ 256자 | 서명 |
| keyId | string |  | ✓|  |  ~ 1024자 | 서명 계산에 사용한 GS2-Key 암호화 키 GRN |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| newContextStack | string | 마스터 데이터를 고정하는 시각을 기록한 컨텍스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Distribute(
    );
    var result = await domain.FreezeMasterDataBySignedTimestampAsync(
        accessToken: null,
        body: "body",
        signature: "signature",
        keyId: "key-0001"
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Distribute(
    );
    var future = domain.FreezeMasterDataBySignedTimestampFuture(
        accessToken: null,
        body: "body",
        signature: "signature",
        keyId: "key-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Distribute(
    );
    const auto Future = Domain->FreezeMasterDataBySignedTimestamp(
        nullptr, // accessToken
        "body", // body
        "signature", // signature
        "key-0001" // keyId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```


---

### runStampSheet

획득 액션을 실행한다(리소스 부여)<br>

트랜잭션의 일부로, 플레이어에게 리소스를 부여하는 획득 액션을 1개 실행합니다.<br>
예를 들어, 아이템 부여, 경험치 가산, 게임 내 화폐 부여 등입니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| stampSheet | string |  | ✓|  |  ~ 5242880자 | 트랜잭션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runStampSheetExpress

트랜잭션 내 모든 액션을 일괄 실행한다(익스프레스 모드)<br>

트랜잭션의 검증·소비·획득 액션을 1회의 API 호출로 한꺼번에 실행합니다. 개별로 실행하는 것보다 고속입니다.<br>
오류가 발생한 경우에는 다시 호출해 주세요. 소비 액션이 중복 적용되지 않도록 하는 구조가 있으므로 안전하게 재시도할 수 있습니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| verifyTaskResultCodes | List&lt;int&gt; | 검증 액션의 실행 상태 코드|
| verifyTaskResults | List&lt;string&gt; | 검증 액션의 실행 결과|
| taskResultCodes | List&lt;int&gt; | 소비 액션의 실행 상태 코드|
| taskResults | List&lt;string&gt; | 소비 액션의 실행 결과|
| sheetResultCode | int | 획득 액션의 실행 상태 코드|
| sheetResult | string | 획득 액션의 실행 결과 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runStampSheetExpressWithoutNamespace

네임스페이스 없이 트랜잭션 내 모든 액션을 일괄 실행한다(익스프레스 모드)<br>

익스프레스 모드의 고속성과 네임스페이스 생략의 경량성을 결합한 버전입니다.<br>
검증·소비·획득 액션을 1회의 호출로 한꺼번에 실행합니다. 중복 실행을 방지하는 구조가 있으므로 안전하게 재시도할 수 있습니다.<br>
트레이드오프: 트랜잭션 로그가 GS2-Log에 기록되지 않고, 오버플로 처리를 사용할 수 없는 등의 제약이 있습니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| stampSheet | string |  | ✓|  |  ~ 5242880자 | 트랜잭션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| verifyTaskResultCodes | List&lt;int&gt; | 검증 액션의 실행 상태 코드|
| verifyTaskResults | List&lt;string&gt; | 검증 액션의 실행 결과|
| taskResultCodes | List&lt;int&gt; | 소비 액션의 실행 상태 코드|
| taskResults | List&lt;string&gt; | 소비 액션의 실행 결과|
| sheetResultCode | int | 획득 액션의 실행 상태 코드|
| sheetResult | string | 획득 액션의 실행 결과 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runStampSheetWithoutNamespace

네임스페이스를 지정하지 않고 획득 액션을 실행한다<br>

네임스페이스 지정을 생략한 RunStampSheet의 경량 버전입니다.<br>
오버헤드는 줄어들지만, 트랜잭션 로그가 GS2-Log에 기록되지 않고 오버플로 처리를 사용할 수 없는 등의 트레이드오프가 있습니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| stampSheet | string |  | ✓|  |  ~ 5242880자 | 트랜잭션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runStampTask

소비 액션을 실행한다(리소스 소비)<br>

트랜잭션의 일부로, 플레이어로부터 리소스를 차감하는 소비 액션을 1개 실행합니다.<br>
예를 들어, 게임 내 화폐 지불, 스태미나 소비, 아이템 사용 등입니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| stampTask | string |  | ✓|  |  ~ 5242880자 | 소비 액션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| contextStack | string | 태스크 실행 결과를 반영한 ContextStack|
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runStampTaskWithoutNamespace

네임스페이스를 지정하지 않고 소비 액션을 실행한다<br>

네임스페이스 지정을 생략한 RunStampTask의 경량 버전입니다.<br>
오버헤드는 줄어들지만, 트랜잭션 로그가 GS2-Log에 기록되지 않고 오버플로 처리를 사용할 수 없는 등의 트레이드오프가 있습니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| stampTask | string |  | ✓|  |  ~ 5242880자 | 소비 액션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| contextStack | string | 태스크 실행 결과를 반영한 ContextStack|
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runVerifyTask

검증 액션을 실행한다(전제 조건 체크)<br>

트랜잭션이 진행되기 전에 전제 조건이 충족되었는지를 체크하는 검증 액션을 1개 실행합니다.<br>
예를 들어, 플레이어가 필요한 아이템을 가지고 있는지, 특정 레벨에 도달했는지 등을 검증합니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| verifyTask | string |  | ✓|  |  ~ 5242880자 | 검증 액션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| contextStack | string | 태스크 실행 결과를 반영한 ContextStack|
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### runVerifyTaskWithoutNamespace

네임스페이스를 지정하지 않고 검증 액션을 실행한다<br>

네임스페이스 지정을 생략한 RunVerifyTask의 경량 버전입니다.<br>
오버헤드는 줄어들지만, 트랜잭션 로그가 GS2-Log에 기록되지 않고 오버플로 처리를 사용할 수 없는 등의 트레이드오프가 있습니다.<br>
일반적으로 직접 호출할 필요는 없습니다. 트랜잭션 처리 시 SDK가 자동으로 처리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| verifyTask | string |  | ✓|  |  ~ 5242880자 | 검증 액션 |
| keyId | string |  | ✓|  |  ~ 1024자 | 암호화 키 GRN |
| contextStack | string |  | |  |  ~ 32768자 | 요청 컨텍스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| contextStack | string | 태스크 실행 결과를 반영한 ContextStack|
| statusCode | int | 상태 코드|
| result | string | 응답 내용|

#### 구현 예제




**Unity (UniTask)**
```csharp
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unity (Vanilla)**
```cs
// New Experience ではSDKレベルで実行されるため明示的にAPIを呼び出す必要はありません
// New Experience runs at the SDK level, so there is no need to explicitly call the API

```

**Unreal Engine 5**
```cpp
// SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### setDefaultConfig

트랜잭션의 기본 설정값을 등록한다<br>

트랜잭션 발행 시 사용되는 기본 Config 값을 보유한 컨텍스트를 준비합니다.<br>
Config는 트랜잭션의 액션에 삽입할 수 있는 변수로서 기능합니다. 예를 들어, 슬롯 이름이나 수량 지정 등에 사용합니다.<br>
여기서 기본값을 설정해 두면, 트랜잭션을 발행할 때마다 매번 지정할 필요가 없어집니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| gameSession | GameSession | | ✓|  |  | GameSession |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | ✓|  | 1 ~ 1000 items | 트랜잭션의 플레이스홀더에 적용하는 설정값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| newContextStack | string | 기본 Config를 반영하기 위한 ContextStack|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: null
    );
    var result = await domain.SetDefaultConfigAsync(
        accessToken: null,
        config: new List<Gs2.Unity.Gs2Distributor.Model.EzConfig> {
            new Gs2.Unity.Gs2Distributor.Model.EzConfig() {
                Key = "key-0001",
                Value = "value-0001",
            },
            new Gs2.Unity.Gs2Distributor.Model.EzConfig() {
                Key = "key-0002",
                Value = "value-0002",
            },
        }
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: null
    );
    var future = domain.SetDefaultConfigFuture(
        accessToken: null,
        config: new List<Gs2.Unity.Gs2Distributor.Model.EzConfig> {
            new Gs2.Unity.Gs2Distributor.Model.EzConfig() {
                Key = "key-0001",
                Value = "value-0001",
            },
            new Gs2.Unity.Gs2Distributor.Model.EzConfig() {
                Key = "key-0002",
                Value = "value-0002",
            },
        }
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        nullptr // namespaceName
    );
    const auto Future = Domain->SetDefaultConfig(
        nullptr, // accessToken
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Distributor::Model::FEzConfig>>>();
            v->Add(
                MakeShared<Gs2::UE5::Distributor::Model::FEzConfig>()
                ->WithKey(TOptional<FString>("key-0001"))
                ->WithValue(TOptional<FString>("value-0001"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Distributor::Model::FEzConfig>()
                ->WithKey(TOptional<FString>("key-0002"))
                ->WithValue(TOptional<FString>("value-0002"))
            );
            return v;
        }() // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```


---

### getStampSheetResult

완료된 트랜잭션의 결과를 취득한다(레거시)<br>

트랜잭션 ID를 지정하여, 과거에 완료된 트랜잭션의 실행 결과를 취득합니다.<br>
결과에는 실행된 각 액션(검증·소비·획득)의 상태와 응답이 포함됩니다.<br>
트랜잭션에서 무슨 일이 일어났는지 확인하기 위해 사용합니다. 예를 들어, 실제로 어떤 보상이 지급되었는지 확인하는 데 유용합니다.<br>

이 API는 레거시(스탬프 시트 방식)의 트랜잭션 결과를 취득합니다. 새로운 트랜잭션 형식의 경우에는 GetTransactionResult를 사용해 주세요.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| transactionId | string |  | ✓|  | 36 ~ 36자 | 트랜잭션 ID<br>이 트랜잭션을 고유하게 식별하는 UUID입니다. 트랜잭션과 그 실행 결과, 그리고 연쇄되는 후속 트랜잭션의 연결에 사용됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzStampSheetResult](#ezstampsheetresult) | 트랜잭션 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).StampSheetResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).StampSheetResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->StampSheetResult(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec" // transactionId
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).me(game_session).stamp_sheet_result(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    )

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.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).StampSheetResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).StampSheetResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->StampSheetResult(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec" // transactionId
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Distributor::Model::FStampSheetResult> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).me(game_session).stamp_sheet_result(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    )

# 이벤트 핸들링 시작
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의 실행에 의해 변화한 것만이 대상이 됩니다.

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

---

### getTransactionResult

완료된 트랜잭션의 결과를 취득한다<br>

트랜잭션 ID를 지정하여, 과거에 완료된 트랜잭션의 실행 결과를 취득합니다.<br>
결과에는 실행된 각 액션(검증·소비·획득)의 상태와 응답이 포함됩니다.<br>
트랜잭션에서 무슨 일이 일어났는지 확인하기 위해 사용합니다. 예를 들어, 실제로 어떤 보상이 지급되었는지, 어떤 리소스가 소비되었는지를 확인하는 데 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| transactionId | string |  | ✓|  | 36 ~ 36자 | 트랜잭션 ID<br>이 분산 트랜잭션을 고유하게 식별하는 UUID입니다. 실행 결과 조회 및 원래 API 요청과의 연결에 사용됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).TransactionResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).TransactionResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->TransactionResult(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec" // transactionId
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).me(game_session).transaction_result(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    )

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.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).TransactionResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Distributor.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).TransactionResult(
        transactionId: "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Distributor->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->TransactionResult(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec" // transactionId
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Distributor::Model::FTransactionResult> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

**Godot**
```gdscript

var domain = ez.distributor.namespace_(
        "namespace-0001"
    ).me(game_session).transaction_result(
        "cc1985c3-54f0-4fc3-b295-dc30214284ec"
    )

# 이벤트 핸들링 시작
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의 실행에 의해 변화한 것만이 대상이 됩니다.

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

---

## 이벤트 핸들러

### OnAutoRunStampSheetNotification

트랜잭션의 자동 실행이 완료되었을 때 푸시 알림

 | 이름 | 타입 | 설명 |
| --- | --- | --- |
| namespaceName | string |네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.|
| userId | string |사용자ID|
| transactionId | string |트랜잭션 ID<br>이 트랜잭션을 고유하게 식별하는 UUID입니다. 트랜잭션과 그 실행 결과, 그리고 연쇄되는 후속 트랜잭션의 연결에 사용됩니다.|

#### 구현 예제





**Unity (UniTask)**
```csharp

    gs2.Distributor.OnAutoRunStampSheetNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var transactionId = notification.TransactionId;
    };
```

**Unity (Vanilla)**
```cs

    gs2.Distributor.OnAutoRunStampSheetNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var transactionId = notification.TransactionId;
    };
```

**Unreal Engine 5**
```cpp

    Gs2->Distributor->OnAutoRunStampSheetNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto TransactionId = Notification->TransactionIdValue;
    });
```

**Godot**
```gdscript

    ez.distributor.auto_run_stamp_sheet_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var user_id = notification.user_id
        var transaction_id = notification.transaction_id
    )
```


---

### OnAutoRunTransactionNotification

트랜잭션의 자동 실행이 완료되었을 때 푸시 알림

 | 이름 | 타입 | 설명 |
| --- | --- | --- |
| namespaceName | string |네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.|
| userId | string |사용자ID|
| transactionId | string |트랜잭션 ID<br>이 분산 트랜잭션을 고유하게 식별하는 UUID입니다. 실행 결과 조회 및 원래 API 요청과의 연결에 사용됩니다.|

#### 구현 예제





**Unity (UniTask)**
```csharp

    gs2.Distributor.OnAutoRunTransactionNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var transactionId = notification.TransactionId;
    };
```

**Unity (Vanilla)**
```cs

    gs2.Distributor.OnAutoRunTransactionNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var transactionId = notification.TransactionId;
    };
```

**Unreal Engine 5**
```cpp

    Gs2->Distributor->OnAutoRunTransactionNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto TransactionId = Notification->TransactionIdValue;
    });
```

**Godot**
```gdscript

    ez.distributor.auto_run_transaction_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var user_id = notification.user_id
        var transaction_id = notification.transaction_id
    )
```


---



