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

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

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



## 모델

### EzProgress

퀘스트 진행 상황<br>

퀘스트 시작 시 생성되며, 종료 시 삭제됩니다.<br>

인게임 도중 앱을 종료한 경우 이 데이터가 남은 상태가 되며<br>
엔티티가 보유한 진행 중인 퀘스트 정보를 통해 게임을 재개할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| progressId | string |  | ※ |  |  ~ 1024자 | 퀘스트 진행 상황 GRN<br>※ 서버가 자동으로 설정 |
| transactionId | string |  | ✓ | UUID |  ~ 36자 | 트랜잭션 ID<br>퀘스트 트랜잭션의 고유 식별자입니다. 퀘스트 진행 상황과 보상 배포를 관리하는 트랜잭션을 연결하는 데 사용됩니다. |
| questModelId | string |  | ✓ |  |  ~ 1024자 | 퀘스트 모델 GRN<br>현재 진행 중인 퀘스트 모델의 GRN입니다. 사용자가 플레이 중인 퀘스트를 식별하며, 퀘스트 도중 앱을 종료한 경우 게임 재개를 가능하게 합니다. |
| randomSeed | long |  | ✓ |  | 0 ~ 9223372036854775805 | 난수 시드<br>퀘스트 시작 시 할당되는 난수 시드입니다. 이 퀘스트 시도에서 선택되는 콘텐츠 배리에이션(보상 세트)을 결정하는 데 사용되며, 재현 가능한 결과를 보장합니다. |
| metadata | string |  |  |  |  ~ 256자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| rewards | [List&lt;EzReward&gt;](#ezreward) |  |  | [] | 0 ~ 1000 items | 클리어 보상 목록<br>퀘스트 클리어 시 지급되는 보상의 목록입니다. 난수 시드로 선택된 콘텐츠 배리에이션에 기반하여 퀘스트 시작 시 결정됩니다. |
| failedRewards | [List&lt;EzReward&gt;](#ezreward) |  |  | [] | 0 ~ 1000 items | 실패 시 보상 목록<br>퀘스트 실패 시 지급되는 보상의 목록입니다. 퀘스트 시작 시 결정되며, 실패에 대한 위로 보상이나 비용 일부 반환으로 제공됩니다. |

**관련 메서드:**
deleteProgress - 플레이어의 현재 퀘스트 취소
end - 퀘스트 완료 또는 실패 보고
getProgress - 플레이어의 현재 퀘스트 진행 상황 조회


---

### EzCompletedQuestList

클리어 완료 퀘스트 목록<br>

퀘스트 그룹 내에서 사용자가 클리어한 퀘스트를 추적합니다. 전제 퀘스트의 클리어 판정 및 최초 클리어 보너스 판정에 사용됩니다. 각 퀘스트 이름은 클리어 횟수에 관계없이 한 번만 기록됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| questGroupName | string |  | ✓ |  |  ~ 128자 | 퀘스트 그룹 모델 이름<br>이 클리어 완료 퀘스트 목록이 속한 퀘스트 그룹의 이름입니다. 사용자별·퀘스트 그룹별로 하나의 CompletedQuestList가 존재합니다. |
| completeQuestNames | List&lt;string&gt; |  |  | [] | 0 ~ 1000 items | 클리어 완료 퀘스트 이름 목록<br>이 퀘스트 그룹 내에서 사용자가 클리어한 퀘스트 이름의 목록입니다. 최초 클리어 시 퀘스트 이름이 추가되며, 중복은 제거됩니다. 전제 퀘스트 조건 평가 및 최초 클리어 보너스 판정에 사용됩니다. |

**관련 메서드:**
describeCompletedQuestLists - 플레이어의 클리어 완료 퀘스트 기록 목록 조회
getCompletedQuestList - 특정 그룹의 플레이어 클리어 완료 퀘스트 기록 조회


---

### EzQuestGroupModel

퀘스트 그룹 모델<br>

퀘스트 그룹은 여러 퀘스트를 그룹화하기 위한 엔티티로, 퀘스트 진행은 그룹 내에서 동시에 하나만 실행할 수 있습니다.<br>
즉, 퀘스트를 병렬로 진행할 수 있도록 하려면 그룹을 분리해야 합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 퀘스트 그룹 모델 이름<br>퀘스트 그룹 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 1024자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| quests | [List&lt;EzQuestModel&gt;](#ezquestmodel) |  |  | [] | 0 ~ 1000 items | 그룹에 속한 퀘스트<br>이 퀘스트 그룹에 속한 퀘스트 모델의 목록입니다. 그룹 내에서는 동시에 하나의 퀘스트만 진행할 수 있습니다. |
| challengePeriodEventId | string |  |  |  |  ~ 1024자 | 도전 가능 기간 이벤트 GRN<br>이 그룹 내 퀘스트에 도전할 수 있는 기간을 설정하는 GS2-Schedule의 이벤트 GRN입니다. 지정한 경우, 이벤트가 활성화된 기간 동안에만 퀘스트를 시작할 수 있습니다. |

**관련 메서드:**
getProgress - 플레이어의 현재 퀘스트 진행 상황 조회
getQuestGroup - 이름을 지정하여 퀘스트 그룹 정의 조회
listQuestGroups - 퀘스트 그룹 모델 목록 조회


---

### EzQuestModel

퀘스트 모델<br>

퀘스트 모델은 인게임 시작에 필요한 대가와 클리어했을 때 얻는 보상을 보유하는 엔티티입니다.<br>

클리어했을 때 얻는 보상은 여러 배리에이션을 준비할 수 있으며, 퀘스트 시작 시 추첨할 수 있습니다.<br>
예를 들어, 퀘스트 자체는 동일하더라도 레어 몬스터의 출현 여부에 따라 두 가지 콘텐츠 배리에이션을 만들 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| questModelId | string |  | ※ |  |  ~ 1024자 | 퀘스트 모델 GRN<br>※ 서버가 자동으로 설정 |
| name | string |  | ✓ |  |  ~ 128자 | 퀘스트 모델 이름<br>퀘스트 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 1024자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| contents | [List&lt;EzContents&gt;](#ezcontents) |  |  | [] | 1 ~ 10 items | 퀘스트 내용<br>이 퀘스트의 콘텐츠 배리에이션 목록입니다. 퀘스트 시작 시 가중치 추첨을 통해 하나의 배리에이션이 선택됩니다. 각 배리에이션마다 서로 다른 클리어 보상을 정의할 수 있어, 동일한 퀘스트라도 다른 결과(예: 레어 몬스터의 출현)를 구현할 수 있습니다. |
| challengePeriodEventId | string |  |  |  |  ~ 1024자 | 도전 가능 기간 이벤트 GRN<br>이 퀘스트에 도전할 수 있는 기간을 설정하는 GS2-Schedule 이벤트 GRN입니다. 지정한 경우, 이벤트가 활성화되어 있는 기간에만 퀘스트를 시작할 수 있습니다. 이 설정은 퀘스트 그룹의 도전 가능 기간보다 우선됩니다. |
| firstCompleteAcquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 10 items | 최초 클리어 보상 입수 액션 리스트<br>이 퀘스트를 처음 클리어했을 때만 실행되는 입수 액션의 리스트입니다. 일반 클리어 보상에 더해 지급되는 보너스 보상으로, 최초 클리어 보너스를 구현하는 데 사용합니다. |
| verifyActions | [List&lt;EzVerifyAction&gt;](#ezverifyaction) |  |  | [] | 0 ~ 10 items | 검증 액션 리스트<br>이 퀘스트를 시작하기 위한 전제 조건이 되는 검증 액션의 리스트입니다. 모든 검증 액션이 성공해야만 퀘스트를 시작할 수 있습니다. 레벨 확인이나 아이템 소지 등의 요건을 강제하는 데 사용합니다. |
| consumeActions | [List&lt;EzConsumeAction&gt;](#ezconsumeaction) |  |  | [] | 0 ~ 10 items | 소비 액션 리스트<br>이 퀘스트의 시작 비용으로 실행되는 소비 액션입니다. 스태미나나 통화 등의 비용이 퀘스트 시작 시 소비됩니다. |
| failedAcquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 100 items | 실패 시 입수 액션 리스트<br>퀘스트 실패 시 실행되는 입수 액션입니다. 실패 시 위로 보상이나 퀘스트 참가 비용의 일부 반환 등에 사용합니다. |
| premiseQuestNames | List&lt;string&gt; |  |  | [] | 0 ~ 10 items | 전제 퀘스트 이름 리스트<br>이 퀘스트에 도전하기 전에 클리어가 필요한 같은 그룹 내 퀘스트 이름의 리스트입니다. 연속되는 퀘스트 체인이나 분기되는 퀘스트 경로 작성에 사용합니다. |

**관련 메서드:**
getProgress - 플레이어의 현재 퀘스트 진행 상황 조회
getQuest - 이름을 지정하여 퀘스트 정의 조회
listQuests - 그룹 내 퀘스트 모델 목록 조회


**관련 모델:**
EzQuestGroupModel - 퀘스트 그룹 모델



---

### EzContents

콘텐츠<br>

퀘스트 콘텐츠의 하나의 배리에이션을 나타냅니다. 각 퀘스트는 서로 다른 보상을 가진 여러 콘텐츠 배리에이션을 가질 수 있으며, 퀘스트 시작 시 가중치 추첨을 통해 하나가 선택됩니다. 메타데이터는 사용자 ID 및 컨피그 값을 이용한 템플릿 변수 치환을 지원합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| metadata | string |  |  |  |  ~ 256자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| completeAcquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 10 items | 클리어 보상 획득 액션<br>이 콘텐츠 배리에이션으로 퀘스트를 클리어했을 때 실행되는 획득 액션입니다. 플레이어가 퀘스트 클리어 시 받게 되는 실제 보상을 정의합니다. |


**관련 모델:**
EzQuestModel - 퀘스트 모델



---

### EzConsumeAction

소비 액션

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


**관련 모델:**
EzQuestModel - 퀘스트 모델



---

### EzVerifyAction

검증 액션

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


**관련 모델:**
EzQuestModel - 퀘스트 모델



---

### EzAcquireAction

입수 액션

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


**관련 모델:**
EzQuestModel - 퀘스트 모델
EzContents - 콘텐츠



---

### EzReward

보상<br>

퀘스트 시작 시 결정되는 개별 보상 아이템을 나타냅니다. 실행할 입수 액션, 대상 리소스, 지급할 수량을 포함합니다. Progress 엔티티에 저장되며, 퀘스트 클리어 또는 실패 시 보상 배포에 사용됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 입수 액션에서 실행할 액션의 종류 |
| request | string |  | ✓ |  |  ~ 5242880자 | 리퀘스트<br>입수 액션 실행 시 사용되는 리퀘스트 파라미터의 JSON 문자열입니다. 대상 네임스페이스, 리소스 이름, 수량 등 보상의 구체적인 세부 사항을 포함합니다. |
| itemId | string |  | ✓ |  |  ~ 1024자 | 아이템 ID<br>보상으로 입수하는 리소스의 GRN입니다. 플레이어에게 지급되는 아이템, 통화, 기타 리소스를 특정합니다. |
| value | int |  | ✓ |  | 0 ~ 2147483646 | 수량<br>보상으로 지급하는 리소스의 수량입니다. 게임 로직에 따라 동적으로 조정할 수 있습니다. |

**관련 메서드:**
end - 퀘스트 완료 또는 실패 보고


**관련 모델:**
EzProgress - 퀘스트 진행 상황



---

### EzConfig

컨피그 설정<br>

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

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

**관련 메서드:**
end - 퀘스트 완료 또는 실패 보고
start - 퀘스트 시작


---

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

**관련 메서드:**
end - 퀘스트 완료 또는 실패 보고
start - 퀘스트 시작


---

## 메서드

### deleteProgress

플레이어의 현재 퀘스트 취소<br>

플레이어의 진행 중인 퀘스트를 삭제하여 다른 퀘스트를 시작할 수 있도록 합니다.<br>
플레이어가 퀘스트를 포기하고자 할 때 사용합니다. 예를 들어 "이 퀘스트를 포기하시겠습니까?"라는 확인 다이얼로그를 표시하고, 플레이어가 확인했을 때 이 API를 호출합니다.<br>
새로운 퀘스트를 시작할 때 사용하는 `force` 옵션의 대안입니다. 이전 퀘스트를 암묵적으로 폐기하는 대신, 플레이어에게 명시적인 "퀘스트 포기" 버튼을 제공하고자 할 때 사용합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzProgress](#ezprogress) | 퀘스트 진행 상황|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    );
    var result = await domain.DeleteProgressAsync(
    );

```

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

```

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

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

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

var result = async_result.result

```


---

### end

퀘스트 완료 또는 실패 보고<br>

플레이어가 퀘스트 플레이를 마쳤음을 서버에 알립니다. 다음 두 가지를 보고해야 합니다:<br>
- `isComplete`: 플레이어가 퀘스트를 클리어했는지(true) 실패했는지(false).<br>
- `rewards`: 플레이어가 퀘스트 중 실제로 획득한 보상. 퀘스트 시작 시 전달받은 최댓값을 초과해서는 안 됩니다.<br>

플레이어가 퀘스트를 클리어한 경우(isComplete = true), 보고된 보상이 플레이어에게 지급됩니다(예: 아이템이 인벤토리에 추가, 재화가 지갑에 추가).<br>
플레이어가 실패한 경우(isComplete = false), rewards 파라미터는 무시되며 퀘스트 정의에 설정된 실패 보상이 대신 지급됩니다.<br>

서버는 보고된 보상을 검증합니다. 허용된 최댓값을 초과하거나 이 퀘스트에 존재하지 않는 아이템을 보고한 경우 오류가 발생합니다.<br>
퀘스트의 게임 플레이가 끝났을 때 사용합니다. 예를 들어, 플레이어가 보스를 물리친 후나 "게임 오버" 화면이 표시된 후입니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| rewards | [List&lt;EzReward&gt;](#ezreward) |  | | [] | 0 ~ 1000 items | 퀘스트에서 실제로 획득한 보상 |
| isComplete | bool |  | ✓|  |  | 퀘스트를 클리어했는지 여부 |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

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

#### 구현 예제




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

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    );
    var future = domain.EndFuture(
        isComplete: true,
        rewards: null,
        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->Quest->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Progress(
    );
    const auto Future = Domain->End(
        true // isComplete
        // rewards
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

var async_result = await domain.end(
    true, # is_complete
    null, # rewards
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### getProgress

플레이어의 현재 퀘스트 진행 상황 조회<br>

플레이어가 현재 플레이 중인 퀘스트를 퀘스트 그룹 및 퀘스트 정의 상세 정보와 함께 조회합니다.<br>
앱을 재시작한 후 퀘스트를 재개할 때 유용합니다. 예를 들어 플레이어가 "스테이지 1-3"을 진행하던 도중 앱을 종료한 경우, 앱 실행 시 이 API를 호출하여 미완료 퀘스트를 감지하고 "퀘스트를 재개하시겠습니까?" 다이얼로그를 표시할 수 있습니다.<br>
플레이어가 진행 중인 퀘스트를 가지고 있지 않은 경우, 진행 데이터는 반환되지 않습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzProgress](#ezprogress) | 퀘스트 진행 상황|
| questGroup | [EzQuestGroupModel](#ezquestgroupmodel) | 퀘스트 그룹 모델|
| quest | [EzQuestModel](#ezquestmodel) | 퀘스트 모델|

#### 구현 예제




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

```

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

```

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

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

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

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

---

### start

퀘스트 시작<br>

플레이어가 퀘스트를 시작한다는 것을 서버에 알립니다. 플레이어는 퀘스트 그룹마다 동시에 하나의 퀘스트만 진행할 수 있습니다. 이미 다른 퀘스트가 진행 중인 경우 이 요청은 실패합니다 (`force` = true를 지정하면 이전 퀘스트를 파기하고 새로 시작할 수 있습니다).<br>

퀘스트가 정상적으로 시작되면 응답에는 다음 정보가 포함됩니다:<br>
- 이 퀘스트에서 획득 가능한 보상의 최댓값 (예: "검 최대 3개, 골드 최대 100개"). 게임 플레이 중 플레이어가 획득할 수 있는 것을 결정하는 데 사용합니다.<br>
- 재현 가능한 게임 플레이를 위한 난수 시드. 이 시드를 사용하면 동일한 조건에서 게임을 재현할 수 있어, 디버깅이나 비정상 종료 후 재개에 유용합니다.<br>
- 이 퀘스트 실행을 고유하게 식별하는 트랜잭션 ID. 퀘스트 결과를 보고할 때 필요합니다.<br>

플레이어가 퀘스트의 "시작"을 탭했을 때 사용합니다. 예를 들어 "1장" 그룹의 "스테이지 1-3"을 시작하는 경우입니다. 스태미나 등의 퀘스트 비용은 자동으로 소비됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| questGroupName | string |  | ✓|  |  ~ 128자 | 퀘스트 그룹 모델 이름 |
| questName | string |  | ✓|  |  ~ 128자 | 퀘스트 모델 이름 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| force | bool |  | | false |  | 이미 시작한 퀘스트가 있는 경우 이를 파기하고 시작할지 여부 |
| 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) | 트랜잭션 실행 결과|

#### Error

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

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| InProgressException | BadRequestException | 퀘스트가 이미 진행 중입니다. |

#### 구현 예제




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

try {
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.StartAsync(
        questGroupName: "group-0001",
        questName: "quest-0001",
        force: null,
        config: null
    );
} catch(Gs2.Gs2Quest.Exception.InProgressException e) {
    // Quest is already underway.
}
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.StartFuture(
        questGroupName: "group-0001",
        questName: "quest-0001",
        force: null,
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Quest.Exception.InProgressException)
        {
            // Quest is already underway.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Quest->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->Start(
        "group-0001", // questGroupName
        "quest-0001" // questName
        // force
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Quest::Error::FInProgressError::Class))
        {
            // Quest is already underway.
        }
        return false;
    }

```

**Godot**
```gdscript

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

var async_result = await domain.start(
    "group-0001", # quest_group_name
    "quest-0001", # quest_name
    null, # force
    null # config
)
if async_result.error != null:
    if async_result.error is Gs2QuestInProgressException:
        # 퀘스트가 이미 진행 중입니다.
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### describeCompletedQuestLists

플레이어의 클리어 완료 퀘스트 기록 목록 조회<br>

모든 퀘스트 그룹에 대한 플레이어의 클리어 완료 퀘스트 기록을 조회합니다.<br>
각 항목은 하나의 퀘스트 그룹에 대응하며, 해당 그룹 내에서 플레이어가 클리어에 성공한 퀘스트 이름 목록을 포함합니다.<br>
퀘스트 진행 상황 개요를 구성할 때 사용합니다. 예를 들어 퀘스트 선택 화면에서 "1장: 5/10 클리어", "2장: 0/8 클리어", "이벤트 던전: 3/3 클리어"와 같이 표시할 수 있습니다.<br>
일부 퀘스트는 특정 이전 퀘스트의 클리어를 전제 조건으로 요구하므로, 어떤 퀘스트가 해제되었는지 판단하는 데도 유용합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzCompletedQuestList&gt;](#ezcompletedquestlist) | 클리어한 퀘스트 리스트 목록|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




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

```

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

```


---

### getCompletedQuestList

특정 그룹의 플레이어 클리어 완료 퀘스트 기록 조회<br>

지정한 퀘스트 그룹 내에서 플레이어가 클리어한 퀘스트 이름 목록을 조회합니다.<br>
특정 그룹 내에서 플레이어가 이미 클리어한 퀘스트를 확인할 때 사용합니다. 예를 들어 "1장"의 각 스테이지별 클리어/미클리어 상태를 표시하거나, 다음 스테이지를 해제하기 위한 전제 퀘스트를 클리어했는지 확인하는 경우에 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| questGroupName | string |  | ✓|  |  ~ 128자 | 퀘스트 그룹 모델 이름<br>이 클리어 완료 퀘스트 목록이 속한 퀘스트 그룹의 이름입니다. 사용자별·퀘스트 그룹별로 하나의 CompletedQuestList가 존재합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCompletedQuestList](#ezcompletedquestlist) | 클리어한 퀘스트 리스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CompletedQuestList(
        questGroupName: "main"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CompletedQuestList(
        questGroupName: "main"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

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

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).completed_quest_list(
        "main"
    )

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

var domain = ez.quest.namespace_(
        "namespace-0001"
    ).me(game_session).completed_quest_list(
        "main"
    )

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

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

---

### getQuestGroup

이름을 지정하여 퀘스트 그룹 정의 조회<br>

이름을 지정하여 퀘스트 그룹을 1건 조회합니다.<br>
조회되는 정보에는 그룹 내 퀘스트 목록과 선택적인 도전 가능 기간 설정(예: 특정 기간에만 도전 가능한 이벤트 던전)이 포함됩니다.<br>
특정 퀘스트 카테고리의 상세 정보를 표시할 때 사용합니다. 예를 들어 "1장"의 모든 스테이지나 "이벤트 던전" 카테고리 내에서 도전 가능한 모든 퀘스트를 표시하는 경우에 유용합니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzQuestGroupModel](#ezquestgroupmodel) | 퀘스트 그룹 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).QuestGroupModel(
        questGroupName: "quest-group-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).QuestGroupModel(
        questGroupName: "quest-group-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

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

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listQuestGroups

퀘스트 그룹 모델 목록 조회<br>

이 네임스페이스에 등록된 모든 퀘스트 그룹 모델을 조회합니다.<br>
퀘스트 그룹은 관련된 퀘스트를 하나로 묶는 카테고리입니다. 예를 들어 "1장", "이벤트 던전", "데일리 퀘스트" 등이 있습니다.<br>
플레이어는 그룹당 하나의 퀘스트만 동시에 진행할 수 있으므로, 그룹은 동시 진행 제한을 관리하는 수단으로도 사용됩니다.<br>
퀘스트 선택 화면을 구성할 때 사용합니다. 예를 들어 "메인 스토리", "서브 퀘스트", "이벤트 던전"과 같은 카테고리를 플레이어에게 표시하여 선택하도록 할 수 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzQuestGroupModel&gt;](#ezquestgroupmodel) | 퀘스트 그룹 모델 목록|

#### 구현 예제




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

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---

### getQuest

이름을 지정하여 퀘스트 정의 조회<br>

그룹 이름과 퀘스트 이름을 지정하여 퀘스트를 1건 조회합니다.<br>
조회되는 정보에는 퀘스트의 보상 설정, 소비 액션(시작 비용), 전제 퀘스트 조건이 포함됩니다.<br>
플레이어가 퀘스트를 시작하기 전에 상세 정보를 표시할 때 사용합니다. 예를 들어 퀘스트 상세 화면에서 "스테이지 1-3: 보상: 검×1, 골드×100 | 비용: 스태미나×10 | 조건: 스테이지 1-2 클리어"와 같이 표시할 수 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzQuestModel](#ezquestmodel) | |

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).QuestGroupModel(
        questGroupName: "quest-group-0001"
    ).QuestModel(
        questName: "quest-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).QuestGroupModel(
        questGroupName: "quest-group-0001"
    ).QuestModel(
        questName: "quest-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Quest->Namespace(
        "namespace-0001" // namespaceName
    )->QuestGroupModel(
        "quest-group-0001" // questGroupName
    )->QuestModel(
        "quest-0001" // questName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

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

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

---

### listQuests

그룹 내 퀘스트 모델 목록 조회<br>

지정한 퀘스트 그룹에 속한 모든 퀘스트 모델을 조회합니다.<br>
각 퀘스트에는 보상(플레이어가 획득할 수 있는 것), 비용(시작에 소비되는 아이템이나 통화), 전제 조건(먼저 클리어해야 하는 퀘스트)이 정의되어 있습니다.<br>
카테고리 내 퀘스트 목록을 표시할 때 사용합니다. 예를 들어 "1장" 그룹 내에서 "스테이지 1-1", "스테이지 1-2", "스테이지 1-3(잠김 — 먼저 1-2를 클리어하세요)"와 같이 표시할 수 있습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzQuestModel&gt;](#ezquestmodel) | 퀘스트 모델 리스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Quest.Namespace(
        namespaceName: "namespace-0001"
    ).QuestGroupModel(
        questGroupName: "quest-group-0001"
    );
    var items = await domain.QuestModelsAsync(
    ).ToListAsync();

```

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

```


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




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

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

```

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

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

```

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

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

```


**⚠️ Warning**

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

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

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

---



