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

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

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



## 모델

### EzReceiveStatus

수신 상태<br>

사용자별·보너스 모델별 로그인 보너스의 수신 상태를 추적합니다.<br>
각 항목이 해당 날짜의 보상을 수신했는지 여부를 나타내는 불리언 배열(receivedSteps)을 보유합니다.<br>
또한 일별 수신 자격을 판정하기 위해 마지막으로 보너스를 수신한 시각(lastReceivedAt)을 기록합니다.<br>
receivedSteps는 보너스 사이클이 재시작될 때(반복이 활성화된 스트리밍 모드 등) 초기화될 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| bonusModelName | string |  | ✓ |  |  ~ 128자 | 보너스 모델 이름<br>이 수신 상태가 연결된 로그인 보너스 모델의 이름.<br>사용자의 수신 진행 상황을 특정 보너스 모델 정의와 연결하여, 어떤 보상 목록과 배포 규칙이 적용되는지를 결정합니다. |
| receivedSteps | List&lt;bool&gt; |  |  | [] | 0 ~ 100 items | 수신 스텝<br>보상 목록의 각 날짜에 대응하는 순서가 있는 불리언 배열.<br>true는 사용자가 해당 날짜의 보상을 수신했음을 나타내고, false는 놓쳤거나 아직 수신하지 않았음을 나타냅니다.<br>배열의 인덱스는 관련된 BonusModel의 rewards 배열과 대응합니다.<br>스트리밍 모드에서 반복이 활성화된 경우, 사이클이 재시작될 때 이 배열은 초기화됩니다. |
| lastReceivedAt | long |  |  |  |  | 마지막 수신 시각<br>사용자가 마지막으로 로그인 보너스를 수신한 시각의 타임스탬프.<br>보너스 모델에 정의된 리셋 시각을 기준으로, 사용자가 오늘의 보너스를 이미 수신했는지 여부를 판정하는 데 사용됩니다.<br>수신 상태가 초기화될 때(반복 모드에서의 사이클 재시작 시 등) 0으로 재설정됩니다. |

**관련 메서드:**
missedReceive - 놓친 로그인 보너스 수령
receive - 오늘의 로그인 보너스 수령
getReceiveStatus - 특정 보너스 스케줄에 대한 플레이어의 로그인 보너스 진행 상황 조회
listReceiveStatuss - 모든 보너스 스케줄에 대한 플레이어의 로그인 보너스 진행 상황 조회


---

### EzBonusModel

로그인 보너스 모델<br>

로그인 보너스 모델에는 로그인 보너스의 배포 스케줄을 설정합니다.<br>
배포 스케줄에는 《스케줄 모드》와 《스트리밍 모드》가 있습니다.<br>

스케줄 모드에서는 GS2-Schedule의 이벤트 지정이 필수이며, 해당 이벤트의 시작일로부터 경과한 일수에 따라 보너스를 배포합니다.<br>
도중에 놓친 날짜가 발생한 경우, 그 날의 보너스는 배포되지 않습니다.<br>

스트리밍 모드에서는 매일 보너스에 설정된 보상을 처음부터 순서대로 배포합니다.<br>
스트리밍 모드에서는 반복 설정이 가능합니다. 이 경우 스트림의 끝에 도달하면 다시 처음부터 배포를 시작합니다.<br>

스케줄 모드·스트리밍 모드 모두 미수령 구제 기능이 있습니다.<br>
일정한 비용을 지불함으로써 놓친 보너스를 수령할 수 있습니다.<br>
단, GS2-Schedule의 이벤트가 연결되어 있는 경우, 이벤트 시작일로부터 경과한 일수보다 앞선 보너스는 받을 수 없습니다.<br>
미수령 구제 기능은 스트리밍 모드이면서 반복이 활성화된 경우에는 사용할 수 없습니다.<br>

스케줄 모드·스트리밍 모드 모두, 설정 가능한 보너스의 최대 일수는 100일입니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 로그인 보너스 모델명<br>로그인 보너스 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| mode | 문자열 열거형<br>enum {<br>"schedule",<br>"streaming"<br>}<br> |  | ✓ |  |  | 모드<br>로그인 보너스의 배포 스케줄 종류를 지정합니다.<br>"schedule" 모드에서는 GS2-Schedule의 이벤트 시작일로부터 경과한 일수를 기준으로 보상이 배포됩니다.<br>"streaming" 모드에서는 달력 날짜와 관계없이 매일 처음부터 순서대로 보상이 배포됩니다.schedule: 스케줄 모드 / streaming: 스트리밍 모드 /  |
| periodEventId | string |  |  |  |  ~ 1024자 | 기간 이벤트 GRN<br>로그인 보너스를 활성화할 기간을 나타내는 GS2-Schedule의 이벤트 GRN입니다.<br>스케줄 모드에서는 필수이며, 보상 배포의 경과 일수를 계산하는 기준이 되는 시작일을 결정합니다.<br>스트리밍 모드에서는 생략 가능하지만, 지정한 경우 이벤트 시작일로부터 경과한 일수보다 앞선 보너스는 받을 수 없게 됩니다. |
| resetHour | int | {periodEventId} == "" | ✓※ |  | 0 ~ 23 | 리셋 시간(UTC)<br>수령 플래그가 리셋되는 시각(0~23, UTC)입니다.<br>로그인 보너스에서 날짜가 바뀌는 시점을 결정합니다.<br>periodEventId가 지정되지 않은 경우에만 필요합니다. 이벤트가 설정되어 있는 경우, 리셋 시점은 이벤트의 스케줄을 따릅니다.<br><br>※ periodEventId이(가) "" 이면 필수 |
| repeat | 문자열 열거형<br>enum {<br>"enabled",<br>"disabled"<br>}<br> | {mode} == "streaming" | ✓※ |  |  | 반복<br>모든 보상을 배포한 후, 처음부터 다시 배포할지 여부입니다.<br>스트리밍 모드에서만 유효합니다. 활성화하면 마지막 보상을 배포한 후 첫 번째 보상으로 돌아가 반복됩니다.<br>주의: 반복이 활성화된 경우, 미수령 구제 기능은 사용할 수 없습니다.enabled: 활성화 / disabled: 비활성화 / <br><br>※ mode이(가) "streaming" 이면 필수 |
| rewards | [List&lt;EzReward&gt;](#ezreward) |  |  |  | 0 ~ 100 items | 보상 목록<br>날짜별 보상의 순서가 지정된 목록입니다. 각 항목은 하루치 로그인 보너스에 대응하며, 인덱스 0부터 순서대로 배포됩니다.<br>스케줄 모드에서는 인덱스가 이벤트 시작일로부터 경과한 일수에 대응합니다.<br>스트리밍 모드에서는 인덱스가 로그인 일수에 대응합니다. 최대 100개 항목까지 설정할 수 있습니다. |
| missedReceiveRelief | 문자열 열거형<br>enum {<br>"enabled",<br>"disabled"<br>}<br> |  |  | "disabled" |  | 미수령 구제 기능<br>놓친 보너스의 구제 기능을 활성화할지 여부입니다. 활성화하면 사용자는 지정된 비용(소비 액션)을 지불함으로써 받지 못한 보너스를 소급하여 수령할 수 있습니다.<br>필요에 따라 구제를 허용하기 전에 조건을 확인하는 검증 액션도 설정할 수 있습니다.<br>스트리밍 모드이면서 반복이 활성화된 경우에는 사용할 수 없습니다. 기본값은 "disabled"입니다.enabled: 활성화 / disabled: 비활성화 /  |
| missedReceiveReliefVerifyActions | [List&lt;EzVerifyAction&gt;](#ezverifyaction) | {missedReceiveRelief} == "enabled" |  | [] | 0 ~ 10 items | 미수령 구제 검증 액션 목록<br>미수령 구제를 허용하기 전에 실행되는 검증 액션의 목록입니다.<br>구제 처리 전에 사용자의 자격 등 전제 조건을 확인합니다. 최대 10개까지 설정할 수 있습니다.<br>missedReceiveRelief가 활성화된 경우에만 적용됩니다.<br><br>※ missedReceiveRelief이(가) "enabled" 이면 활성화 |
| missedReceiveReliefConsumeActions | [List&lt;EzConsumeAction&gt;](#ezconsumeaction) | {missedReceiveRelief} == "enabled" |  | [] | 0 ~ 10 items | 미수령 구제 소비 액션 목록<br>놓친 보너스를 구제하기 위해 사용자가 지불해야 하는 비용을 정의하는 소비 액션의 목록입니다.<br>예를 들어 게임 내 화폐나 아이템을 구제 비용으로 소비하도록 설정할 수 있습니다. 최대 10개까지 설정할 수 있습니다.<br>missedReceiveRelief가 활성화된 경우에만 적용됩니다.<br><br>※ missedReceiveRelief이(가) "enabled" 이면 활성화 |

**관련 메서드:**
missedReceive - 놓친 로그인 보너스 수령
receive - 오늘의 로그인 보너스 수령
getBonusModel - 특정 로그인 보너스의 스케줄 조회
listBonusModels - 로그인 보너스의 스케줄 목록 취득
getReceiveStatus - 특정 보너스 스케줄에 대한 플레이어의 로그인 보너스 진행 상황 조회


---

### EzReward

보상<br>

로그인 보너스의 하루치 보상 설정을 나타냅니다.<br>
각 Reward에는 사용자가 수신할 항목(아이템, 화폐, 경험치 등)을 정의하는 입수 액션 목록이 포함됩니다.<br>
BonusModel의 rewards 배열은 하루당 하나의 Reward를 보유하며, 순서대로 배포됩니다.<br>
보상 값은 버프 시스템(BonusModelBuff)을 통해 실행 시점에 변경할 수 있으며, 입수 액션에 배율을 적용할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| acquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  | ✓ |  | 1 ~ 10 items | 입수 액션 목록<br>이 날짜의 보상으로 사용자에게 부여되는 리소스를 정의하는 입수 액션 목록.<br>각 액션은 입수 액션(아이템 추가, 화폐 부여 등)과 그 요청 파라미터를 지정합니다.<br>보상당 최소 1개, 최대 10개의 액션을 설정할 수 있습니다. |


**관련 모델:**
EzBonusModel - 로그인 보너스 모델



---

### EzConfig

Config 설정<br>

트랜잭션 변수에 적용할 설정값의 키-값 쌍입니다.<br>
Config 엔트리를 통해 실행 시점에 획득 액션의 동적인 매개변수화가 가능합니다.<br>
예를 들어 슬롯 이름이나 그 밖의 문맥에 따라 달라지는 값을 Config 설정을 통해 트랜잭션 요청에 주입할 수 있어,<br>
마스터 데이터를 변경하지 않고도 유연한 보상 설정을 구현할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| key | string |  | ✓ |  |  ~ 64자 | 키<br>트랜잭션 매개변수 내에서 치환되는 변수명입니다. 최대 64자. |
| value | string |  |  |  |  ~ 51200자 | 값<br>트랜잭션 매개변수 내에서 대응하는 키에 대입되는 값입니다. 최대 51,200자. |

**관련 메서드:**
missedReceive - 놓친 로그인 보너스 수령
receive - 오늘의 로그인 보너스 수령


---

### EzConsumeAction

소비 액션<br>

소비 액션의 구조를 통해 사용자로부터 리소스를 소비하는 액션을 정의합니다.<br>
미수령 보너스 구제에서 사용자가 지불해야 하는 비용(화폐 차감, 아이템 소비 등)을 지정하는 데 사용됩니다.<br>
action 필드는 소비 액션의 종류를 지정하고, request 필드에는 그에 대응하는 요청 매개변수가 포함됩니다.

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


**관련 모델:**
EzBonusModel - 로그인 보너스 모델



---

### EzVerifyAction

검증 액션<br>

작업을 실행하기 전에 조건을 검증하는 액션을 정의합니다.<br>
미수령 보너스 구제에서 구제를 허용하기 전에 전제 조건(사용자 자격, 리소스 이용 가능 여부 등)을 확인하는 데 사용됩니다.<br>
action 필드는 검증 액션의 종류를 지정하고, request 필드에는 그에 대응하는 요청 매개변수가 포함됩니다.

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


**관련 모델:**
EzBonusModel - 로그인 보너스 모델



---

### EzAcquireAction

획득 액션<br>

획득 액션의 구조를 통해 사용자에게 리소스를 부여하는 액션을 정의합니다.<br>
보상 내에서 사용되며, 사용자가 받는 것(인벤토리에 아이템 추가, 화폐 부여, 경험치 부여 등)을 지정합니다.<br>
action 필드는 획득 액션의 종류를 지정하고, request 필드에는 그에 대응하는 요청 매개변수가 포함됩니다.

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


**관련 모델:**
EzReward - 보상



---

### 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 | 획득 액션 실행 결과 리스트 |

**관련 메서드:**
missedReceive - 놓친 로그인 보너스 수령
receive - 오늘의 로그인 보너스 수령


---

## 메서드

### missedReceive

놓친 로그인 보너스 수령<br>

과거에 로그인하지 못해 놓친 날짜의 보너스를 나중에 수령할 수 있습니다.<br>
이 기능을 사용하려면 보너스 모델에서 "미수령 구제"가 활성화되어 있어야 합니다.<br>
활성화된 경우, 플레이어는 비용을 지불하여 놓친 보상을 수령할 수 있습니다. 예를 들어 "젬 50개를 소비하여 3일차의 보상을 수령"하는 식으로 사용할 수 있습니다.<br>

스케줄 모드에서는 이벤트 시작일로부터 경과한 일수까지의 보상만 구제할 수 있습니다.<br>
스트리밍 모드에서는 단계 번호를 자동으로 판정할 수 있으므로 생략할 수 있습니다.<br>

스트리밍 모드에서 "반복"이 활성화되어 있는 경우, 이 기능은 사용할 수 없습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| bonusModelName | string |  | ✓|  |  ~ 128자 | 로그인 보너스 모델명<br>로그인 보너스 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| stepNumber | int |  | |  | 0 ~ 100 | 수령할 스텝 번호. 스트리밍 모드에서는 생략할 수 있습니다 |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzReceiveStatus](#ezreceivestatus) | 수령 상태|
| bonusModel | [EzBonusModel](#ezbonusmodel) | 로그인 보너스 모델|
| transactionId | string | 발행된 트랜잭션 ID|
| stampSheet | string | 로그인 보너스 수령 실행에 사용하는 스탬프 시트|
| stampSheetEncryptionKeyId | string | 스탬프 시트의 서명 계산에 사용한 암호화 키 GRN|
| autoRunStampSheet | bool | 트랜잭션 자동 실행이 활성화되어 있는지 여부|
| atomicCommit | bool | 트랜잭션을 원자적으로 커밋할지 여부|
| transaction | string | 발행된 트랜잭션|
| transactionResult | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### Error

이 API에는 특별한 예외가 정의되어 있습니다.<br>
GS2-SDK for Game Engine에서는 게임 내에서 핸들링이 필요할 것으로 예상되는 에러를, 일반적인 예외에서 파생된 특수화된 예외로 제공하여 다루기 쉽게 하고 있습니다.<br>
일반적인 에러의 종류와 핸들링 방법은 [여기]() 문서를 참고해 주세요.

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| AlreadyReceivedException | BadRequestException | 오늘의 로그인 보너스는 이미 수령했습니다. |

#### 구현 예제




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

try {
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Bonus(
    );
    var result = await domain.MissedReceiveAsync(
        bonusModelName: "bonus-0001",
        stepNumber: 1,
        config: null
    );
} catch(Gs2.Gs2LoginReward.Exception.AlreadyReceivedException e) {
    // You have already received today's login bonus.
}
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Bonus(
    );
    var future = domain.MissedReceiveFuture(
        bonusModelName: "bonus-0001",
        stepNumber: 1,
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2LoginReward.Exception.AlreadyReceivedException)
        {
            // You have already received today's login bonus.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->LoginReward->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Bonus(
    );
    const auto Future = Domain->MissedReceive(
        "bonus-0001", // bonusModelName
        1 // stepNumber
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::LoginReward::Error::FAlreadyReceivedError::Class))
        {
            // You have already received today's login bonus.
        }
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.login_reward.namespace_(
        "namespace-0001"
    ).me(game_session).bonus(
    )

var async_result = await domain.missed_receive(
    "bonus-0001", # bonus_model_name
    1, # step_number
    null # config
)
if async_result.error != null:
    if async_result.error is Gs2LoginRewardAlreadyReceivedException:
        # 오늘의 로그인 보너스는 이미 수령했습니다.
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### receive

오늘의 로그인 보너스 수령<br>

지정된 보너스 모델을 기준으로 오늘 분의 로그인 보너스를 수령합니다.<br>
각 보너스 모델에는 날짜별 보상이 순서대로 정의되어 있습니다. 예를 들어 "1일차: 젬 100개, 2일차: 스태미나 회복제 5개, 3일차: 레어 가챠 티켓, ..."과 같이 설정할 수 있습니다.<br>
플레이어는 로그인할 때마다 이 API를 호출하여 보상 단계를 순서대로 진행합니다.<br>

보너스 배포 방식에는 두 가지가 있습니다:<br>
- 스케줄 모드: 특정 달력 기간에 연동되어 보상이 배포됩니다. 로그인하지 않은 날짜의 보상은 건너뜁니다.<br>
- 스트리밍 모드: 달력 날짜와 관계없이 로그인할 때마다 처음부터 순서대로 보상이 배포됩니다.<br>

이미 오늘의 보너스를 수령한 경우 오류가 발생합니다.<br>
모든 보상을 배포한 후 "반복"이 활성화되어 있으면(스트리밍 모드에서만) 첫 번째 보상으로 돌아가 주기가 다시 시작됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| bonusModelName | string |  | ✓|  |  ~ 128자 | 로그인 보너스 모델명<br>로그인 보너스 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzReceiveStatus](#ezreceivestatus) | 수령 상태|
| bonusModel | [EzBonusModel](#ezbonusmodel) | 로그인 보너스 모델|
| transactionId | string | 발행된 트랜잭션 ID|
| stampSheet | string | 로그인 보너스 수령 실행에 사용하는 스탬프 시트|
| stampSheetEncryptionKeyId | string | 스탬프 시트의 서명 계산에 사용한 암호화 키 GRN|
| autoRunStampSheet | bool | 트랜잭션 자동 실행이 활성화되어 있는지 여부|
| atomicCommit | bool | 트랜잭션을 원자적으로 커밋할지 여부|
| transaction | string | 발행된 트랜잭션|
| transactionResult | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### Error

이 API에는 특별한 예외가 정의되어 있습니다.<br>
GS2-SDK for Game Engine에서는 게임 내에서 핸들링이 필요할 것으로 예상되는 에러를, 일반적인 예외에서 파생된 특수화된 예외로 제공하여 다루기 쉽게 하고 있습니다.<br>
일반적인 에러의 종류와 핸들링 방법은 [여기]() 문서를 참고해 주세요.

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| AlreadyReceivedException | BadRequestException | 오늘의 로그인 보너스는 이미 수령했습니다. |

#### 구현 예제




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

try {
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Bonus(
    );
    var result = await domain.ReceiveAsync(
        bonusModelName: "bonus-0001",
        config: null
    );
} catch(Gs2.Gs2LoginReward.Exception.AlreadyReceivedException e) {
    // You have already received today's login bonus.
}
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Bonus(
    );
    var future = domain.ReceiveFuture(
        bonusModelName: "bonus-0001",
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2LoginReward.Exception.AlreadyReceivedException)
        {
            // You have already received today's login bonus.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->LoginReward->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Bonus(
    );
    const auto Future = Domain->Receive(
        "bonus-0001" // bonusModelName
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::LoginReward::Error::FAlreadyReceivedError::Class))
        {
            // You have already received today's login bonus.
        }
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.login_reward.namespace_(
        "namespace-0001"
    ).me(game_session).bonus(
    )

var async_result = await domain.receive(
    "bonus-0001", # bonus_model_name
    null # config
)
if async_result.error != null:
    if async_result.error is Gs2LoginRewardAlreadyReceivedException:
        # 오늘의 로그인 보너스는 이미 수령했습니다.
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### getBonusModel

특정 로그인 보너스의 스케줄 조회<br>

보너스 모델명을 지정하여 하나의 로그인 보너스 모델의 상세 정보를 조회합니다.<br>
특정 보너스의 상세 화면을 표시할 때 사용합니다. 예를 들어 7일치 보상을 목록으로 표시하고, 이미 수령한 날짜에 체크 표시를 하는 화면입니다.<br>

반환되는 모델에는 보상 목록, 보너스 모드, 반복 설정, 미수령 구제 설정이 포함됩니다.<br>
GetReceiveStatus와 조합하면 어느 날짜의 보상을 이미 수령했는지, 어느 날짜가 아직 수령 가능한지를 파악할 수 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzBonusModel](#ezbonusmodel) | 로그인 보너스 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).BonusModel(
        bonusModelName: "bonus-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).BonusModel(
        bonusModelName: "bonus-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

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

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listBonusModels

로그인 보너스의 스케줄 목록 취득<br>

네임스페이스에 설정된 모든 로그인 보너스 모델을 취득합니다.<br>
각 모델은 보상 스케줄을 정의합니다. 1일차에 무엇을 받는지, 2일차에 무엇을 받는지와 같은 내용입니다.<br>

로그인 보너스의 목록 화면을 만들 때 사용합니다.<br>
예를 들어 "7일간 신규 유저 보너스"와 "월간 로그인 보너스"가 동시에 진행 중인 경우, 이 API로 두 정보를 모두 취득할 수 있습니다.<br>

반환되는 모델에는 보너스 모드(스케줄 / 스트리밍), 일별 보상 목록, 반복 여부, 놓친 보너스 구제 가능 여부가 포함됩니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzBonusModel&gt;](#ezbonusmodel) | 로그인 보너스 모델 목록|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### getReceiveStatus

특정 보너스 스케줄에 대한 플레이어의 로그인 보너스 진행 상황 조회<br>

하나의 로그인 보너스 모델에 대한 플레이어의 수령 상태를 조회합니다.<br>
수령 상태에는 각 날짜의 수령 완료/미수령 여부를 나타내는 불리언 값 목록(receivedSteps)이 포함됩니다. 예를 들어 [true, true, false, true, false, false, false]는 "1일차와 2일차는 수령 완료, 3일차는 미수령, 4일차는 수령 완료, 5~7일차는 아직 도달하지 않음"을 의미합니다.<br>

GetBonusModel과 조합하여 각 날짜의 보상 내용과 수령 상태를 함께 표시하는 로그인 보너스 상세 화면을 만드는 데 사용합니다.<br>

응답에는 보너스 모델의 상세 정보도 포함되어 있어, 한 번의 API 호출로 보상 내용과 수령 상태를 모두 표시할 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| bonusModelName | string |  | ✓|  |  ~ 128자 | 보너스 모델 이름<br>이 수신 상태가 연결된 로그인 보너스 모델의 이름.<br>사용자의 수신 진행 상황을 특정 보너스 모델 정의와 연결하여, 어떤 보상 목록과 배포 규칙이 적용되는지를 결정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzReceiveStatus](#ezreceivestatus) | 수령 상태|
| bonusModel | [EzBonusModel](#ezbonusmodel) | 로그인 보너스 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveStatus(
        bonusModelName: "bonus-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveStatus(
        bonusModelName: "bonus-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->LoginReward->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->ReceiveStatus(
        "bonus-0001" // bonusModelName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.login_reward.namespace_(
        "namespace-0001"
    ).me(game_session).receive_status(
        "bonus-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.LoginReward.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveStatus(
        bonusModelName: "bonus-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listReceiveStatuss

모든 보너스 스케줄에 대한 플레이어의 로그인 보너스 진행 상황 조회<br>

플레이어가 관계한 모든 로그인 보너스 모델의 수령 상태를 조회합니다.<br>
각 상태에서 어느 날짜의 보상을 이미 수령했는지, 어느 날짜가 아직 수령 가능한지를 알 수 있습니다.<br>

로그인 보너스 개요 화면을 만들 때 사용합니다. 예를 들어 "7일간 신규 보너스: 4/7 수령 완료", "월간 보너스: 12/30 수령 완료"와 같이 진행 상황을 표시할 수 있습니다.<br>

게임 시작 시 아직 수령하지 않은 보너스가 있는지 확인하여 플레이어에게 수령을 유도하는 데에도 유용합니다.

#### Request

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

#### Result

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

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---



