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

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

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



## 모델

### EzComplete

미션 달성 상황<br>

특정 미션 그룹에 대한 사용자의 미션 달성 상황과 보상 수령 상황을 추적합니다. 달성 완료된 태스크명과 보상 수령 완료된 태스크명을 각각 별도의 목록으로 관리하여, 달성된 태스크와 실제로 보상을 수령한 태스크를 구분합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| missionGroupName | string |  | ✓ |  |  ~ 128자 | 미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다. |
| completedMissionTaskNames | List&lt;string&gt; |  |  | [] | 0 ~ 1000 items | 달성 완료된 태스크명 목록<br>사용자가 달성한(달성 조건을 충족한) 미션 태스크의 이름입니다. 카운터가 목표값에 도달하거나 검증 액션이 성공한 시점에 이 목록에 추가됩니다. 보상 수령 여부는 관계없습니다. |
| receivedMissionTaskNames | List&lt;string&gt; |  |  | [] | 0 ~ 1000 items | 보상 수령 완료된 태스크명 목록<br>사용자가 달성 보상을 이미 수령한 미션 태스크의 이름입니다. 보상을 받으려면 태스크가 달성 완료 목록에 포함되어 있어야 합니다. |

**관련 메서드:**
evaluateComplete - 미션 달성 상태를 재평가합니다
getComplete - 특정 미션 그룹에 대한 플레이어의 달성 상태를 취득합니다
listCompletes - 전체 그룹에 대한 플레이어의 미션 달성 상황 조회
decreaseCounter - 카운터를 감소시키기


---

### EzCounter

카운터<br>

카운터는 미션 진행 상황을 게임 플레이어별로 보관하는 엔티티입니다.<br>
카운터의 값은 연결된 태스크의 기간별로 집계됩니다.<br>

따라서 하나의 카운터는 여러 개의 값을 가집니다.<br>
예를 들어, 퀘스트 클리어 횟수 카운터라면 이번 달 클리어 횟수, 이번 주 클리어 횟수, 오늘 클리어 횟수와 같은 식입니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 카운터 모델 이름<br>이 카운터 인스턴스의 기반이 되는 카운터 모델의 이름입니다. 스코프와 리셋 타이밍을 정의하는 카운터 모델 정의에 연결됩니다. |
| values | [List&lt;EzScopedValue&gt;](#ezscopedvalue) |  |  | [] | 0 ~ 32 items | 값<br>이 카운터의 스코프별 값 리스트입니다. 각 엔트리는 특정 스코프(리셋 타이밍 또는 검증 액션 조건)의 카운터 값과 다음 리셋 시각을 보관합니다. 하나의 카운터가 여러 스코프의 값을 동시에 보관합니다. |

**관련 메서드:**
decreaseCounter - 카운터를 감소시키기
deleteCounter - 카운터를 완전히 삭제
getCounter - 특정 카운터에 대한 플레이어의 값 조회
listCounters - 플레이어의 현재 카운터 값 조회
resetCounter - 카운터의 특정 스코프 리셋


---

### EzCounterScopeModel

카운터 리셋 타이밍 모델<br>

카운터의 스코프를 정의하고, 카운터 값의 리셋 방법과 타이밍을 결정합니다. 스코프는 리셋 타이밍(매일, 매주, 매월, 일정 일수마다, 또는 리셋 없음) 또는 검증 액션 조건 중 하나입니다. 각 카운터는 여러 스코프를 가질 수 있으며, 서로 다른 기간의 값을 추적할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| scopeType | 문자열 열거형<br>enum {<br>"resetTiming",<br>"verifyAction"<br>}<br> |  |  | "resetTiming" |  | 스코프의 종류<br>카운터 스코프의 정의 방법을 결정합니다. "resetTiming" 은 정기적인 리셋 스케줄을 사용하고, "verifyAction" 은 검증 액션으로 카운터 값이 적용되는지 여부를 판정합니다.resetTiming: 리셋 타이밍 / verifyAction: 검증 액션 /  |
| resetType | 문자열 열거형<br>enum {<br>"notReset",<br>"daily",<br>"weekly",<br>"monthly",<br>"days"<br>}<br> |  |  | "notReset" |  | 리셋 타이밍<br>이 스코프의 카운터 값이 리셋되는 타이밍을 결정합니다. 리셋하지 않음(영구 누계), 매일, 매주, 매월, 일정 일수마다 중에서 선택합니다. scopeType 이 "resetTiming" 인 경우에만 사용됩니다.notReset: 리셋 안 함 / daily: 매일 / weekly: 매주 / monthly: 매월 / days: 일정 일수마다 /  |
| resetDayOfMonth | int | {resetType} == "monthly" | ✓※ |  | 1 ~ 31 | 리셋할 날짜<br>카운터 값이 리셋되는 월의 날짜입니다. 지정한 값이 해당 월의 일수를 초과하는 경우, 그 달의 마지막 날로 처리됩니다. resetType 이 "monthly" 인 경우에만 사용됩니다.<br><br>※ resetType이(가) "monthly" 이면 필수 |
| resetDayOfWeek | 문자열 열거형<br>enum {<br>"sunday",<br>"monday",<br>"tuesday",<br>"wednesday",<br>"thursday",<br>"friday",<br>"saturday"<br>}<br> | {resetType} == "weekly" | ✓※ |  |  | 리셋할 요일<br>카운터 값이 리셋되는 요일입니다. resetType 이 "weekly" 인 경우에만 사용됩니다.sunday: 일요일 / monday: 월요일 / tuesday: 화요일 / wednesday: 수요일 / thursday: 목요일 / friday: 금요일 / saturday: 토요일 / <br><br>※ resetType이(가) "weekly" 이면 필수 |
| resetHour | int | {resetType} in ["monthly", "weekly", "daily"] | ✓※ |  | 0 ~ 23 | 리셋 시각<br>카운터 값이 리셋되는 시각(0~23)입니다. 매일, 매주, 매월 리셋 타입과 조합하여 사용됩니다.<br><br>※ resetType이(가) "monthly","weekly","daily"이면 필수 |
| conditionName | string | {scopeType} == "verifyAction" | ✓※ |  |  ~ 128자 | 조건명<br>이 검증 액션 조건 스코프를 식별하는 고유한 이름입니다. 카운터 내에서 대응하는 스코프 값을 조회하는 데 사용됩니다. scopeType 이 "verifyAction" 인 경우에만 사용됩니다.<br><br>※ scopeType이(가) "verifyAction" 이면 필수 |
| condition | [EzVerifyAction](#ezverifyaction) | {scopeType} == "verifyAction" | ✓※ |  |  | 조건<br>이 스코프의 카운터 값이 적용되는지 여부를 판정하는 검증 액션입니다. scopeType이 "verifyAction"인 경우에만 사용됩니다.<br><br>※ scopeType이(가) "verifyAction" 이면 필수 |
| anchorTimestamp | long | {resetType} == "days" | ✓※ |  |  | 경과 일수를 계산하는 기준 일시<br>UNIX 시간(밀리초)<br><br>※ resetType이(가) "days" 이면 필수 |
| days | int | {resetType} == "days" | ✓※ |  | 1 ~ 2147483646 | 리셋하는 일수<br>기준 일시부터 카운트되는 카운터 값의 리셋 간격 일수입니다. resetType이 "days"인 경우에만 사용됩니다.<br><br>※ resetType이(가) "days" 이면 필수 |


**관련 모델:**
EzCounterModel - 카운터 모델



---

### EzCounterModel

카운터 모델<br>

카운터 모델은 미션 태스크의 달성 조건으로 설정할 수 있는 엔티티입니다.<br>
카운터 값은 여러 미션 그룹에서 참조할 수 있기 때문에, 하나의 카운터를 위클리 미션과 데일리 미션 같은 여러 미션 그룹의 달성 조건으로 설정할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 카운터 모델명<br>카운터 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 1024자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| scopes | [List&lt;EzCounterScopeModel&gt;](#ezcounterscopemodel) |  |  | [] | 1 ~ 20 items | 카운터의 리셋 타이밍 목록<br>이 카운터의 스코프(리셋 타이밍 또는 검증 액션 조건)를 정의합니다. 하나의 카운터에 여러 스코프를 설정할 수 있으며, 서로 다른 기간의 값(예: 데일리, 위클리, 누계를 동시에)을 추적할 수 있습니다. |
| challengePeriodEventId | string |  |  |  |  ~ 1024자 | 카운터를 조작할 수 있는 기간을 설정한 GS2-Schedule 이벤트 GRN<br>이 카운터의 증감이 가능한 기간을 정의하는 GS2-Schedule 이벤트를 지정합니다. 설정하지 않은 경우, 카운터는 언제든지 조작할 수 있습니다. |

**관련 메서드:**
getCounterModel - 특정 카운터 정의의 상세 정보를 취득합니다
listCounterModels - 카운터 정의 목록을 취득합니다


---

### EzMissionGroupModel

미션 그룹 모델<br>

미션 그룹은 카운터의 리셋 타이밍으로 태스크를 그룹화하는 엔티티입니다.<br>
예를 들어, 데일리 미션으로 하나의 그룹, 위클리 미션으로 하나의 그룹이 됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 미션 그룹 모델 이름<br>미션 그룹 모델 고유의 이름. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 1024자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| tasks | [List&lt;EzMissionTaskModel&gt;](#ezmissiontaskmodel) |  |  | [] | 0 ~ 1000 items | 미션 태스크 리스트<br>이 그룹에 속하는 미션 태스크입니다. 각 태스크는 달성 조건(카운터의 임계값 또는 검증 액션)과 달성 시 부여되는 보상을 정의합니다. |
| resetType | 문자열 열거형<br>enum {<br>"notReset",<br>"daily",<br>"weekly",<br>"monthly",<br>"days"<br>}<br> |  |  | "notReset" |  | 리셋 타이밍<br>미션 그룹의 달성 상황이 리셋되는 타이밍을 결정합니다. 리셋하지 않음(영구), 매일, 매주, 매월, 기준 일시부터 일정 일수마다 중에서 선택합니다.notReset: 리셋 안 함 / daily: 매일 / weekly: 매주 / monthly: 매월 / days: 일정 일수마다 /  |
| resetDayOfMonth | int | {resetType} == "monthly" | ✓※ |  | 1 ~ 31 | 리셋하는 날짜<br>미션 그룹이 리셋되는 월의 날짜입니다. 지정한 값이 해당 월의 일수를 초과하는 경우, 그 달의 마지막 날로 처리됩니다. resetType이 "monthly"인 경우에만 사용됩니다.<br><br>※ resetType이(가) "monthly" 이면 필수 |
| resetDayOfWeek | 문자열 열거형<br>enum {<br>"sunday",<br>"monday",<br>"tuesday",<br>"wednesday",<br>"thursday",<br>"friday",<br>"saturday"<br>}<br> | {resetType} == "weekly" | ✓※ |  |  | 리셋하는 요일<br>미션 그룹이 리셋되는 요일입니다. resetType이 "weekly"인 경우에만 사용됩니다.sunday: 일요일 / monday: 월요일 / tuesday: 화요일 / wednesday: 수요일 / thursday: 목요일 / friday: 금요일 / saturday: 토요일 / <br><br>※ resetType이(가) "weekly" 이면 필수 |
| resetHour | int | {resetType} in ["monthly", "weekly", "daily"] | ✓※ |  | 0 ~ 23 | 리셋 시각<br>미션 그룹이 리셋되는 시각(0~23)입니다. 매일, 매주, 매월 리셋 타입과 조합하여 사용됩니다.<br><br>※ resetType이(가) "monthly","weekly","daily"이면 필수 |
| completeNotificationNamespaceId | string |  |  |  |  ~ 1024자 | 미션 태스크를 달성했을 때의 푸시 통지<br>이 그룹 내의 미션 태스크가 달성되었을 때 푸시 통지를 전송하는 데 사용되는 GS2-Gateway의 네임스페이스 GRN입니다. 게임 클라이언트에 실시간으로 통지할 수 있습니다. |

**관련 메서드:**
getMissionGroupModel - 특정 미션 그룹의 상세 정보를 취득합니다
listMissionGroupModels - 미션 그룹 목록을 취득합니다


---

### EzMissionTaskModel

미션 태스크 모델<br>

미션 태스크는 연결된 카운터의 값이 일정 수준을 초과하면 보상을 받을 수 있는 조건을 정의하는 엔티티입니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 미션 태스크 모델 이름<br>미션 태스크 모델 고유의 이름. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 1024자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| verifyCompleteType | 문자열 열거형<br>enum {<br>"counter",<br>"verifyActions"<br>}<br> |  |  | "counter" |  | 달성 조건 종류<br>미션 태스크의 달성 판정 방법을 지정합니다. "counter"는 관련된 카운터의 스코프 값이 목표 임곗값에 도달했는지 확인합니다. "verifyActions"는 검증 액션을 사용하여 달성 조건을 확인합니다.counter: 카운터 / verifyActions: 검증 액션 /  |
| targetCounter | [EzTargetCounterModel](#eztargetcountermodel) | {verifyCompleteType} == "counter" | ✓※ |  |  | 목표 카운터<br>미션 태스크의 달성 판정에 사용되는 카운터, 스코프, 목표값을 정의합니다. 카운터의 스코프 값이 지정된 목표값에 도달하거나 초과한 경우, 태스크가 달성된 것으로 간주됩니다.<br><br>※ verifyCompleteType이(가) "counter" 이면 필수 |
| verifyCompleteConsumeActions | [List&lt;EzVerifyAction&gt;](#ezverifyaction) | {verifyCompleteType} == "verifyActions" |  | [] | 0 ~ 10 items | 태스크 달성 판정에 사용하는 검증 액션<br>미션 태스크의 달성 판정에 사용되는 검증 액션의 목록입니다. 모든 검증 액션이 성공한 경우 태스크가 달성된 것으로 간주됩니다. verifyCompleteType이 "verifyActions"인 경우에만 사용됩니다.<br><br>※ verifyCompleteType이(가) "verifyActions" 이면 활성화 |
| completeAcquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 100 items | 미션 달성 시 보상<br>플레이어가 미션 달성 보상을 받을 때 실행되는 입수 액션의 목록입니다. |
| challengePeriodEventId | string |  |  |  |  ~ 1024자 | 보상을 받을 수 있는 기간을 설정한 GS2-Schedule 이벤트 GRN<br>미션 태스크의 보상을 받을 수 있는 기간을 정의하는 GS2-Schedule 이벤트를 지정합니다. 설정하지 않은 경우, 달성 후 언제든지 보상을 받을 수 있습니다. |
| premiseMissionTaskName | string |  |  |  |  ~ 128자 | 이 태스크에 도전하기 위해 달성해 두어야 하는 태스크의 이름<br>이 태스크의 보상을 받기 전에 달성해 두어야 하는, 같은 그룹 내의 전제 미션 태스크를 지정합니다. 단계적인 미션 체인을 만드는 데 사용합니다. |

**관련 메서드:**
getMissionTaskModel - 특정 미션 태스크의 상세 정보를 취득합니다
listMissionTaskModels - 그룹 내 미션 태스크 목록을 취득합니다


**관련 모델:**
EzMissionGroupModel - 미션 그룹 모델



---

### EzTargetCounterModel

목표 카운터<br>

미션의 달성 목표가 되는 카운터의 정보

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| counterName | string |  | ✓ |  |  ~ 128자 | 카운터 모델명<br>카운터 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| scopeType | 문자열 열거형<br>enum {<br>"resetTiming",<br>"verifyAction"<br>}<br> |  |  | "resetTiming" |  | 스코프 종류<br>미션 달성 판정에 사용하는 카운터 스코프의 종류를 지정합니다. "resetTiming"은 특정 리셋 기간의 카운터 값을 평가하고, "verifyAction"은 이름이 지정된 조건의 값을 평가합니다.resetTiming: 리셋 타이밍 / verifyAction: 검증 액션 /  |
| resetType | 문자열 열거형<br>enum {<br>"notReset",<br>"daily",<br>"weekly",<br>"monthly",<br>"days"<br>}<br> | {scopeType} == "resetTiming" |  |  |  | 목표 리셋 타이밍<br>목표값과 비교할 카운터의 리셋 타이밍 스코프를 지정합니다. 예를 들어 "daily"를 선택하면 데일리 카운터 값을 확인합니다. 생략한 경우, 미션 그룹의 리셋 타이밍이 사용됩니다.notReset: 리셋 안 함 / daily: 매일 / weekly: 매주 / monthly: 매월 / days: 일정 일수마다 / <br><br>※ scopeType이(가) "resetTiming" 이면 활성화 |
| conditionName | string | {scopeType} == "verifyAction" | ✓※ |  |  ~ 128자 | 조건 이름<br>목표값과 비교할 검증 액션 조건 스코프의 이름입니다. 카운터 모델의 스코프에서 정의된 conditionName과 일치해야 합니다. scopeType이 "verifyAction"인 경우에만 사용됩니다.<br><br>※ scopeType이(가) "verifyAction" 이면 필수 |
| value | long |  | ✓ |  | 0 ~ 9223372036854775805 | 목표값<br>미션 태스크가 달성된 것으로 간주되기 위해, 카운터의 스코프 값이 도달하거나 초과해야 하는 임곗값입니다. |


**관련 모델:**
EzMissionTaskModel - 미션 태스크 모델



---

### EzConfig

컨피그 설정<br>

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

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

**관련 메서드:**
batchReceiveRewards - 여러 개의 달성 미션 보상을 한꺼번에 수령합니다
receiveRewards - 달성한 미션의 보상을 수령합니다


---

### EzAcquireAction

입수 액션

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


**관련 모델:**
EzMissionTaskModel - 미션 태스크 모델



---

### EzConsumeAction

소비 액션

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


---

### EzVerifyAction

검증 액션<br>

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

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


**관련 모델:**
EzCounterScopeModel - 카운터 리셋 타이밍 모델
EzMissionTaskModel - 미션 태스크 모델



---

### EzScopedValue

스코프 값<br>

특정 스코프 내의 카운터 값을 나타냅니다. 각 스코프 값은 특정 리셋 타이밍(예: 매일, 매주, 매월) 또는 검증 액션 조건의 누적 카운트를 보유합니다. 리셋 타이밍이 도래하면 값은 0으로 리셋됩니다. 카운터 값에는 상한이 있으며, 증가하더라도 최댓값을 초과하지 않습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| scopeType | 문자열 열거형<br>enum {<br>"resetTiming",<br>"verifyAction"<br>}<br> |  |  | "resetTiming" |  | 스코프 종류<br>이 스코프 값이 리셋 타이밍 스케줄에 기반한 것인지, 검증 액션 조건에 기반한 것인지를 나타냅니다.resetTiming: 리셋 타이밍 / verifyAction: 검증 액션 /  |
| resetType | 문자열 열거형<br>enum {<br>"notReset",<br>"daily",<br>"weekly",<br>"monthly",<br>"days"<br>}<br> | {scopeType} == "resetTiming" | ✓※ |  |  | 리셋 타이밍<br>이 스코프 값의 리셋 타이밍입니다. 카운터 값이 리셋될 때까지의 누적 기간을 결정합니다. scopeType이 "resetTiming"인 경우에만 적용됩니다.notReset: 리셋 안 함 / daily: 매일 / weekly: 매주 / monthly: 매월 / days: 일정 일수마다 / <br><br>※ scopeType이(가) "resetTiming" 이면 필수 |
| conditionName | string | {scopeType} == "verifyAction" | ✓※ |  |  ~ 128자 | 조건 이름<br>이 스코프 값이 대응하는 검증 액션 조건의 이름입니다. 이 값이 어느 조건 스코프에 속하는지 식별하는 데 사용됩니다. scopeType이 "verifyAction"인 경우에만 적용됩니다.<br><br>※ scopeType이(가) "verifyAction" 이면 필수 |
| value | long |  |  | 0 | 0 ~ 9223372036854775805 | 카운트<br>이 스코프의 누적 카운터 값입니다. 카운터가 증가하면 늘어나고 감소하면 줄어듭니다. 값은 최댓값으로 상한이 설정되며, 0 미만으로 내려가지 않습니다. |

**관련 메서드:**
resetCounter - 카운터의 특정 스코프 리셋


**관련 모델:**
EzCounter - 카운터



---

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

**관련 메서드:**
batchReceiveRewards - 여러 개의 달성 미션 보상을 한꺼번에 수령합니다
receiveRewards - 달성한 미션의 보상을 수령합니다


---

## 메서드

### batchReceiveRewards

여러 개의 달성 미션 보상을 한꺼번에 수령합니다<br>

같은 그룹 내의 여러 미션 태스크의 보상을 한 번의 호출로 수령합니다.<br>
미션 UI의 "일괄 수령" 버튼에 대응합니다. 플레이어가 각 미션의 "수령하기"를 하나씩 탭하는 대신, 한꺼번에 수령할 수 있습니다.<br>

지정된 모든 태스크는 달성 완료 상태이며 아직 수령하지 않은 상태여야 합니다. 모든 태스크의 보상이 하나의 트랜잭션으로 합쳐집니다.<br>

예를 들어 "전투에서 3회 승리"(보상: 젬 50개)와 "골드 500 수집"(보상: 가챠 티켓 1장)을 달성한 경우, 두 태스크 이름을 함께 지정하여 호출하면 젬 50개 + 가챠 티켓 1장이 한 번의 조작으로 지급됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| missionGroupName | string |  | ✓|  |  ~ 128자 | 미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다. |
| missionTaskNames | List&lt;string&gt; |  | ✓|  | 1 ~ 100 items | 태스크 이름 리스트 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

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

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var result = await domain.BatchReceiveRewardsAsync(
        missionTaskNames: new List<string> {
            "mission-task-0001",
            "mission-task-0002",
        },
        config: null
    );
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var future = domain.BatchReceiveRewardsFuture(
        missionTaskNames: new List<string> {
            "mission-task-0001",
            "mission-task-0002",
        },
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->BatchReceiveRewards(
        []
        {
            auto v = TOptional<TArray<FString>>();
            v->Add("mission-task-0001");
            v->Add("mission-task-0002");
            return v;
        }() // missionTaskNames
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).complete(
        "mission-group-0001"
    )

var async_result = await domain.batch_receive_rewards(
    [
        "mission-task-0001",
        "mission-task-0002",
    ], # mission_task_names
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### evaluateComplete

미션 달성 상태를 재평가합니다<br>

지정된 그룹 내의 모든 카운터 값을 미션 태스크 조건과 대조하여 달성 상태를 갱신합니다.<br>

일반적으로 미션 달성 판정은 카운터가 가산될 때마다 자동으로 이루어집니다. 그러나 카운터가 이미 가산된 후에 기존 그룹에 새로운 미션 태스크를 추가한 경우, 새로운 태스크는 자동으로 평가되지 않습니다.<br>

이러한 상황에서 이 API를 호출하면, 플레이어의 기존 카운터 값이 새로운 태스크의 조건을 이미 충족하고 있는지를 소급하여 확인할 수 있습니다.<br>

예: 데일리 미션에 "전투에서 1회 승리"를 새로 추가한 경우. 오늘 이미 전투에서 승리한 플레이어는 조건을 충족하는 카운터 값을 가지고 있지만, 시스템은 아직 이를 인식하지 못한 상태입니다. EvaluateComplete 를 호출하면 확인이 이루어져 달성 완료로 표시됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| missionGroupName | string |  | ✓|  |  ~ 128자 | 미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzComplete](#ezcomplete) | 재평가 후의 달성 상황|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var result = await domain.EvaluateCompleteAsync(
    );
    var item = await result.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var future = domain.EvaluateCompleteFuture(
    );
    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;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->EvaluateComplete(
    );
    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();

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).complete(
        "mission-group-0001"
    )

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

var result = async_result.result

```


---

### getComplete

특정 미션 그룹에 대한 플레이어의 달성 상태를 취득합니다<br>

지정된 미션 그룹 내에서 플레이어가 어떤 미션 태스크를 달성했고 어떤 보상을 수령했는지를 취득합니다.<br>

특정 그룹의 미션 목록 화면을 표시할 때 사용합니다. 예를 들어 각 데일리 미션과 그 상태를 다음과 같이 표시할 수 있습니다:<br>
- "전투에서 3회 승리" — 달성, 보상 수령 완료(체크 표시)<br>
- "골드 500 수집" — 달성, 보상 수령 가능!(수령 버튼)<br>
- "아이템 10회 사용" — 진행 중: 7/10(진행률 바)<br>

ListMissionTaskModels 나 GetMissionGroupModel 과 조합하면 태스크 정의(목표, 임계값, 보상)를 얻을 수 있고, GetCounter 와 조합하면 진행률 바 표시용 현재 카운터 값을 얻을 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| missionGroupName | string |  | ✓|  |  ~ 128자 | 미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzComplete](#ezcomplete) | 달성 상황|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listCompletes

전체 그룹에 대한 플레이어의 미션 달성 상황 조회<br>

모든 미션 그룹의 달성 상황과 보상 수령 상황을 조회합니다.<br>
각 항목에는 플레이어가 어떤 미션 태스크를 달성했는지(카운터의 임계값을 충족했는지)와 어떤 보상을 수령했는지가 포함됩니다.<br>

미션 개요 화면을 만들 때 사용합니다. 예를 들어, 미수령 보상이 있는 그룹에 배지나 알림 점을 표시할 수 있습니다:<br>
「데일리 미션(보상 2건 수령 가능!)」「위클리 미션(완료)」「업적(신규 1건!)」<br>

미션 태스크에는 두 가지 상태가 있습니다:<br>
- 달성(Completed): 카운터가 임계값을 충족한 상태(예: 「배틀에서 5회 승리」에서 5회 이상 승리한 경우)<br>
- 수령(Received): 달성한 태스크의 보상을 플레이어가 수령한 상태<br>

「달성 완료이지만 미수령」 상태의 태스크는 플레이어가 보상을 획득했지만 아직 수령하지 않았음을 의미합니다. UI에서는 이 상태를 강조 표시해야 합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzComplete&gt;](#ezcomplete) | 달성 상황 리스트|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### receiveRewards

달성한 미션의 보상을 수령합니다<br>

플레이어가 달성한 미션 태스크의 보상을 수령합니다.<br>
태스크는 달성 완료(카운터가 임계값을 충족한 상태) 상태이며 아직 수령하지 않은 상태여야 합니다.<br>

호출하면 설정된 보상이 플레이어에게 지급됩니다. 예를 들어 젬 100개, 가챠 티켓, 골드 500과 같은 보상입니다.<br>

미션 UI의 "수령하기" "받기" 버튼에 대응합니다. 일반적인 흐름은 다음과 같습니다:<br>
1. 플레이어가 달성 완료되어 수령 가능한 보상이 있는 미션을 확인합니다<br>
2. 플레이어가 "수령하기" 버튼을 탭합니다<br>
3. 게임이 ReceiveRewards 를 호출합니다<br>
4. 보상이 지급되고 태스크가 "수령 완료"로 표시됩니다<br>

태스크가 아직 달성되지 않았거나 보상을 이미 수령한 경우에는 오류가 반환됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| missionGroupName | string |  | ✓|  |  ~ 128자 | 미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다. |
| missionTaskName | string |  | ✓|  |  ~ 128자 | 태스크 이름<br>태스크 고유의 이름입니다. 영숫자와 -(하이픈), _(언더스코어), .(마침표)를 사용하여 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

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

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var result = await domain.ReceiveRewardsAsync(
        missionTaskName: "mission-task-0001",
        config: null
    );
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    );
    var future = domain.ReceiveRewardsFuture(
        missionTaskName: "mission-task-0001",
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->ReceiveRewards(
        "mission-task-0001" // missionTaskName
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).complete(
        "mission-group-0001"
    )

var async_result = await domain.receive_rewards(
    "mission-task-0001", # mission_task_name
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### decreaseCounter

카운터를 감소시키기<br>

지정한 카운터의 값을 감소시킵니다. 감소시킬 값을 지정합니다.<br>
현재 시점에서 유효한 스코프만 감소 대상이 됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 모델 이름<br>이 카운터 인스턴스의 기반이 되는 카운터 모델의 이름입니다. 스코프와 리셋 타이밍을 정의하는 카운터 모델 정의에 연결됩니다. |
| value | long |  | ✓|  | 1 ~ 9223372036854775805 | 감산할 값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 감산된 카운터|
| changedCompletes | [List&lt;EzComplete&gt;](#ezcomplete) | 갱신된 달성 상황 리스트|

#### Error

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

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| ConflictException | ConflictException | 카운터 상승 처리가 충돌했습니다. 재시도가 필요합니다 |

#### 구현 예제




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

try {
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var result = await domain.DecreaseCounterAsync(
        value: 1L
    );
    var item = await result.ModelAsync();
    var changedCompletes = result.ChangedCompletes;
} catch(Gs2.Gs2Mission.Exception.ConflictException e) {
    // The counter ascent process has conflicted. Retry required.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var future = domain.DecreaseCounterFuture(
        value: 1L
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Mission.Exception.ConflictException)
        {
            // The counter ascent process has conflicted. Retry required.
        }
        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 changedCompletes = future.Result.ChangedCompletes;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "counter-0001" // counterName
    );
    const auto Future = Domain->DecreaseCounter(
        1L // value
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Mission::Error::FConflictError::Class))
        {
            // The counter ascent process has conflicted. Retry required.
        }
        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 ChangedCompletes = Result->ChangedCompletes;

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "counter-0001"
    )

var async_result = await domain.decrease_counter(
    1 # value
)
if async_result.error != null:
    if async_result.error is Gs2MissionConflictException:
        # 카운터 상승 처리가 충돌했습니다. 재시도가 필요합니다
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### deleteCounter

카운터를 완전히 삭제<br>

플레이어의 지정된 카운터와 그 모든 스코프 값을 삭제합니다.<br>
ResetCounter(특정 스코프만 리셋)와 달리, 플레이어가 한 번도 진행 상황을 가진 적이 없었던 것처럼 카운터 전체를 삭제합니다.<br>

특정 카운터에 대한 플레이어의 진행 상황을 완전히 초기화하고 싶을 때 사용합니다. 예를 들어, 미션의 완전 리셋 기능을 구현하는 경우 등입니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 모델 이름<br>이 카운터 인스턴스의 기반이 되는 카운터 모델의 이름입니다. 스코프와 리셋 타이밍을 정의하는 카운터 모델 정의에 연결됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 삭제한 카운터|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var result = await domain.DeleteCounterAsync(
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var future = domain.DeleteCounterFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "counter-0001" // counterName
    );
    const auto Future = Domain->DeleteCounter(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "counter-0001"
    )

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

var result = async_result.result

```


---

### getCounter

특정 카운터에 대한 플레이어의 값 조회<br>

플레이어의 특정 카운터의 현재 값을 모든 스코프 값을 포함하여 조회합니다.<br>
예를 들어 「battle_wins」 카운터의 경우, 일간=3, 주간=12, 누계=87 과 같은 값이 반환됩니다.<br>

특정 목표에 대한 미션 진행 상황을 표시할 때 사용합니다. 예를 들어 데일리 미션 옆에 진행률 바 「오늘의 배틀 승리 수 3/5」와 같이 표시할 수 있습니다.<br>

각 스코프 값은 서로 다른 기간에 걸쳐 추적된 카운터를 나타내며, 단기적인 진행 상황과 장기적인 진행 상황을 모두 표시할 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 모델 이름<br>이 카운터 인스턴스의 기반이 되는 카운터 모델의 이름입니다. 스코프와 리셋 타이밍을 정의하는 카운터 모델 정의에 연결됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 카운터|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "quest_complete"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "quest_complete"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

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

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "quest_complete"
    )

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.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "quest_complete"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

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

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

```

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

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

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "quest_complete"
    )

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

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

---

### listCounters

플레이어의 현재 카운터 값 조회<br>

플레이어의 모든 카운터 값을 조회합니다.<br>
각 카운터는 특정 플레이어 액션(배틀 승리 횟수, 아이템 수집 수, 골드 획득량 등)을 추적하며, 각 스코프(일간·주간·월간·누계)별 값을 가집니다.<br>

플레이어의 미션 진행 상황 개요를 표시할 때 사용합니다. 예를 들어 「오늘의 배틀 승리 수: 3」이나 「퀘스트 누적 클리어 수: 42」와 같이 상태나 미션 화면에서 표시할 수 있습니다.<br>

카운터 값은 플레이어가 게임 내에서 액션을 수행했을 때(다른 서비스의 보상 액션을 통해) 자동으로 가산되며, 미션 태스크의 임계값과 자동으로 대조됩니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzCounter&gt;](#ezcounter) | 카운터 리스트|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### resetCounter

카운터의 특정 스코프 리셋<br>

지정된 스코프의 카운터 값만 리셋합니다.<br>
예를 들어, 주간이나 누계 값에 영향을 주지 않고 일간 스코프만 리셋할 수 있습니다.<br>

특정 기간의 진행 상황을 수동으로 리셋하고 싶을 때 사용합니다. 예를 들어, 플레이어가 특수 아이템을 사용해 데일리 미션을 재도전할 때 「데일리 챌린지」 카운터를 리셋하는 경우입니다.<br>

지정된 스코프 타입과 일치하는 스코프별 값만 리셋되며, 그 외의 스코프별 값은 변경되지 않습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 모델 이름<br>이 카운터 인스턴스의 기반이 되는 카운터 모델의 이름입니다. 스코프와 리셋 타이밍을 정의하는 카운터 모델 정의에 연결됩니다. |
| scopes | [List&lt;EzScopedValue&gt;](#ezscopedvalue) |  | ✓|  | 1 ~ 20 items | 스코프 리스트 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 삭제한 카운터|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var result = await domain.ResetCounterAsync(
        scopes: new List<Gs2.Unity.Gs2Mission.Model.EzScopedValue> {
            new Gs2.Unity.Gs2Mission.Model.EzScopedValue() {
                ResetType = "daily",
            },
            new Gs2.Unity.Gs2Mission.Model.EzScopedValue() {
                ResetType = "weekly",
            },
        }
    );
    var item = await result.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "counter-0001"
    );
    var future = domain.ResetCounterFuture(
        scopes: new List<Gs2.Unity.Gs2Mission.Model.EzScopedValue> {
            new Gs2.Unity.Gs2Mission.Model.EzScopedValue() {
                ResetType = "daily",
            },
            new Gs2.Unity.Gs2Mission.Model.EzScopedValue() {
                ResetType = "weekly",
            },
        }
    );
    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;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "counter-0001" // counterName
    );
    const auto Future = Domain->ResetCounter(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Mission::Model::FEzScopedValue>>>();
            v->Add(
                MakeShared<Gs2::UE5::Mission::Model::FEzScopedValue>()
                ->WithResetType(TOptional<FString>("daily"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Mission::Model::FEzScopedValue>()
                ->WithResetType(TOptional<FString>("weekly"))
            );
            return v;
        }() // scopes
    );
    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();

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "counter-0001"
    )

var async_result = await domain.reset_counter(
    [
        Gs2MissionEzScopedValue.new()
            .with_reset_type("daily"),
        Gs2MissionEzScopedValue.new()
            .with_reset_type("weekly"),
    ] # scopes
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### getCounterModel

특정 카운터 정의의 상세 정보를 취득합니다<br>

카운터 이름을 지정하여 스코프와 리셋 조건을 포함한 상세 정보를 취득합니다.<br>
카운터가 무엇을 추적하고 그 값이 어떻게 관리되는지를 파악할 때 사용합니다. 예를 들어 미션의 진행에 어떤 액션이 기여하는지를 플레이어에게 표시하는 경우 등입니다.<br>

응답에는 이 카운터에 정의된 스코프 목록이 포함되며, 각 스코프에는 리셋 타입(일별·주별·월별·없음)과 리셋 타이밍이 설정되어 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounterModel](#ezcountermodel) | 카운터 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).CounterModel(
        counterName: "counter-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).CounterModel(
        counterName: "counter-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

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

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listCounterModels

카운터 정의 목록을 취득합니다<br>

네임스페이스에 정의된 모든 카운터 모델을 취득합니다.<br>
카운터는 플레이어의 행동을 추적하고 미션 달성 판정에 사용되는 값입니다. 예를 들어 "battle_wins" 카운터는 전투 승리 횟수를 추적하고, "gold_collected" 카운터는 획득한 골드의 합계를 추적합니다.<br>

각 카운터 모델에서는 하나 이상의 "스코프"를 정의합니다. 스코프는 카운터 값이 어떤 기간 단위로 추적되는지를 결정합니다:<br>
- 하나의 카운터로 일별·주별·월별·누계 값을 동시에 추적할 수 있습니다<br>
- 예를 들어 "battle_wins" 카운터는 오늘의 승리 수(일별 스코프), 이번 주의 승리 수(주별 스코프), 누계 승리 수(누계 스코프)를 가질 수 있습니다<br>
- 서로 다른 미션 태스크가 같은 카운터의 서로 다른 스코프를 참조할 수 있습니다(예: "오늘 전투에서 3회 승리"는 일별 스코프를, "누계 100회 승리"는 누계 스코프를 사용)<br>

카운터 값은 일반적으로 다른 GS2 서비스의 보상 액션으로서 자동으로 가산됩니다(예: 퀘스트 클리어 시나 아이템 구매 시)만, 게임 서버에서 수동으로 가산할 수도 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzCounterModel&gt;](#ezcountermodel) | 카운터 모델 리스트|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### getMissionGroupModel

특정 미션 그룹의 상세 정보를 취득합니다<br>

미션 그룹 이름을 지정하여 리셋 타입, 리셋 타이밍 설정, 그리고 포함된 미션 태스크 목록을 포함한 상세 정보를 취득합니다.<br>

특정 그룹 내의 미션 목록을 표시할 때 사용합니다. 예를 들어 플레이어가 "데일리 미션" 탭을 탭했을 때, 이 API를 호출하여 모든 데일리 미션 태스크와 그 상세 정보를 취득합니다.<br>

응답에는 그룹에 정의된 미션 태스크가 포함되며, 각 태스크에는 대상 카운터 조건과 보상 설정이 있습니다.<br>
GetComplete 와 조합하면 각 태스크에 대한 플레이어의 진행 상황과 달성 상태를 표시할 수 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzMissionGroupModel](#ezmissiongroupmodel) | 미션 그룹 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->MissionGroupModel(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listMissionGroupModels

미션 그룹 목록을 취득합니다<br>

네임스페이스에 정의된 모든 미션 그룹을 취득합니다.<br>
미션 그룹은 개별 미션을 하나로 묶는 카테고리입니다. 예를 들어 "데일리 미션", "위클리 미션", "스토리 미션", "업적 미션"과 같은 것입니다.<br>

각 그룹에는 리셋 타입이 있으며, 그룹 내 미션이 언제 리셋되는지를 결정합니다:<br>
- notReset: 리셋하지 않음("스테이지 10 클리어", "캐릭터 100체 수집"과 같은 영구적인 업적)<br>
- daily: 매일 리셋(예: "오늘 전투에서 3회 승리")<br>
- weekly: 매주 리셋(예: "이번 주 5일 로그인")<br>
- monthly: 매월 리셋(예: "이번 달 골드 10,000 소비")<br>

미션의 메인 목록 화면을 만들 때 사용합니다. 예를 들어 "데일리", "위클리", "업적" 탭을 표시하는 화면입니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzMissionGroupModel&gt;](#ezmissiongroupmodel) | 미션 그룹 모델 리스트|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### getMissionTaskModel

특정 미션 태스크의 상세 정보를 취득합니다<br>

지정된 미션 그룹 내의 특정 미션 태스크를 이름을 지정하여 취득합니다.<br>
특정 미션의 상세 화면을 표시할 때 사용합니다. 목표, 현재 진행 상황, 보상, 달성 여부를 표시할 수 있습니다.<br>

응답에는 다음이 포함됩니다:<br>
- 대상 카운터 이름과 임계값(플레이어가 달성해야 하는 목표)<br>
- 보상 액션(수령 시 플레이어가 획득하는 것)<br>
- 전제 태스크(먼저 달성이 필요한 태스크)가 있는 경우 그 정보<br>
- 달성 판정의 검증 타입

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzMissionTaskModel](#ezmissiontaskmodel) | 미션 태스크 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    ).MissionTaskModel(
        missionTaskName: "mission-task-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    ).MissionTaskModel(
        missionTaskName: "mission-task-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->MissionGroupModel(
        "mission-group-0001" // missionGroupName
    )->MissionTaskModel(
        "mission-task-0001" // missionTaskName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.mission.namespace_(
        "namespace-0001"
    ).mission_group_model(
        "mission-group-0001"
    ).mission_task_model(
        "mission-task-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.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    ).MissionTaskModel(
        missionTaskName: "mission-task-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listMissionTaskModels

그룹 내 미션 태스크 목록을 취득합니다<br>

지정된 미션 그룹 내의 모든 개별 미션 태스크를 취득합니다.<br>
각 미션 태스크는 하나의 미션 목표를 나타냅니다. 예를 들어 "전투에서 5회 승리", "골드 1,000 수집", "스테이지 3 클리어"와 같은 것입니다.<br>

각 태스크에서는 다음이 정의됩니다:<br>
- 대상 카운터와 임계값(예: 카운터 "battle_wins" 가 5 이상)<br>
- 플레이어가 달성 보상을 수령했을 때 지급되는 보상(예: 젬 100개)<br>
- 전제 태스크(선택 사항)(예: "전투에서 10회 승리"는 "전투에서 5회 승리" 달성 후에만 표시됨)<br>

미션 시스템은 다음과 같이 자동으로 동작합니다:<br>
1. 플레이어가 게임 내에서 어떤 행동을 하면(전투 승리, 골드 수집 등) 대응하는 카운터가 가산됩니다<br>
2. 시스템이 카운터 값이 태스크의 임계값을 충족하는지 확인합니다<br>
3. 충족하면 태스크가 "달성"으로 표시됩니다<br>
4. 플레이어는 ReceiveRewards 를 사용하여 보상을 수령할 수 있습니다<br>

그룹 내 각 태스크의 목표와 보상을 포함한 미션 목록을 표시할 때 사용합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzMissionTaskModel&gt;](#ezmissiontaskmodel) | 미션 태스크 모델 리스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    );
    var items = await domain.MissionTaskModelsAsync(
    ).ToListAsync();

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

## 이벤트 핸들러

### OnCompleteNotification

미션 태스크를 달성했을 때 사용하는 푸시 알림

 | 이름 | 타입 | 설명 |
| --- | --- | --- |
| namespaceName | string |네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.|
| groupName | string |미션 그룹명<br>이 달성 상황 레코드가 속한 미션 그룹의 이름입니다. 사용자별·미션 그룹별로 하나의 달성 상황 레코드가 존재합니다.|
| userId | string |사용자ID|
| taskName | string |미션 태스크 이름|

#### 구현 예제





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

    gs2.Mission.OnCompleteNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var groupName = notification.GroupName;
        var userId = notification.UserId;
        var taskName = notification.TaskName;
    };
```

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

    gs2.Mission.OnCompleteNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var groupName = notification.GroupName;
        var userId = notification.UserId;
        var taskName = notification.TaskName;
    };
```

**Unreal Engine 5**
```cpp

    Gs2->Mission->OnCompleteNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto GroupName = Notification->GroupNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto TaskName = Notification->TaskNameValue;
    });
```

**Godot**
```gdscript

    ez.mission.complete_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var group_name = notification.group_name
        var user_id = notification.user_id
        var task_name = notification.task_name
    )
```


---



