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

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

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



## 모델

### EzJob

잡<br>

잡 큐란 즉시 처리를 완료하지 않고 처리를 지연 실행하기 위한 구조입니다.<br>
예를 들어 캐릭터를 입수했을 때 즉시 실행해야 하는 처리는 소지품에 캐릭터를 저장하는 것입니다.<br>
반면, 즉시 처리하지 않아도 되는 처리로는 `도감에 등록한다`는 처리가 있습니다.<br>

이처럼 즉시 처리할 필요가 없는 처리를 잡 큐를 경유하여 처리하도록 하면 장애에 강한 설계로 만들 수 있습니다.<br>
왜냐하면 도감 서비스가 어떤 장애로 인해 정지되어 있더라도, 도감에 등록되지 않은 상태로 게임을 계속할 수 있기 때문입니다.<br>
잡 큐에 쌓인 처리는 실패하더라도 장애가 해소된 후 재시도함으로써 결과적으로 올바른 상태로 만들 수 있습니다.<br>

GS2에서는 이러한 `최종 일관성` 처리를 권장하며, 다양한 상황에서 잡 큐를 이용한 지연 처리가 이루어집니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| jobId | string |  | ※ |  |  ~ 1024자 | 잡 GRN<br>※ 서버가 자동으로 설정 |
| scriptId | string |  | ✓ |  |  ~ 1024자 | 스크립트 GRN |
| args | string |  | ✓ |  |  ~ 5242880자 | 인수<br>잡의 실행 시 스크립트에 전달할 JSON 형식의 요청 파라미터입니다. 액션 타입이나 대상 리소스 등 구체적인 조작 내용을 포함합니다. 최대 5MB입니다. |
| currentRetryCount | int |  |  | 0 | 0 ~ 100 | 현재 재시도 횟수<br>실패 후 이 잡이 재시도된 횟수입니다. 재시도 가능한 오류로 실행이 종료될 때마다 증가합니다. 이 횟수가 maxTryCount에 도달하면 잡은 영구적인 실패로 표시됩니다. |
| maxTryCount | int |  |  | 3 | 1 ~ 100 | 최대 시도 횟수<br>최초 시도와 재시도를 포함하여 이 잡을 실행할 수 있는 최대 횟수입니다. 모든 시도가 실패하면 잡은 포기됩니다. 기본값은 3, 최대값은 100입니다. |

**관련 메서드:**
run - 플레이어의 잡 큐에 있는 다음 잡을 실행한다


---

### EzJobResult

잡 실행 결과(상세)<br>

단일 잡 실행 시도의 결과를 기록합니다. 각 시도마다 개별 JobResult가 생성되므로, 여러 번 재시도된 잡에는 여러 개의 결과가 존재합니다. statusCode는 잡이 성공했는지 실패했는지를 나타냅니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| statusCode | int |  | ✓ |  | 0 ~ 1000 | 상태 코드<br>스크립트 실행에서 반환된 HTTP 상태 코드입니다. 2xx 코드는 성공을 나타내고, 그 외의 코드는 실패를 나타냅니다. 재시도 가능한 오류인 경우 maxTryCount에 도달하지 않았다면 자동으로 재시도가 이루어질 수 있습니다. |
| result | string |  | ✓ |  |  ~ 5242880자 | 응답 내용<br>스크립트 실행에서 반환된 JSON 형식의 응답 본문입니다. 성공 시에는 결과 데이터를, 실패 시에는 오류 상세 정보를 포함합니다. 최대 5MB입니다. |

**관련 메서드:**
getResult - 완료된 잡의 실행 결과를 조회한다


---

### EzJobEntry

등록 잡<br>

잡 큐에 새로운 잡을 등록하기 위한 파라미터를 나타냅니다. 실행할 스크립트, JSON 인수, 최대 재시도 횟수를 포함합니다. 잡을 큐에 푸시할 때의 입력으로 사용됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| scriptId | string |  | ✓ |  |  ~ 1024자 | 스크립트 GRN |
| args | string |  |  | "{}" |  ~ 131072자 | 인수<br>잡 실행 시 스크립트에 전달할 JSON 형식의 요청 파라미터입니다. 기본값은 빈 JSON 객체 "{}" 입니다. 최대 128KB입니다. |
| maxTryCount | int |  |  | 3 | 0 ~ 100 | 최대 시도 횟수<br>최초 시도와 재시도를 포함하여 잡을 실행할 수 있는 최대 횟수입니다. 기본값은 3이며, 최대값은 100입니다. |


---

### EzJobResultBody

잡의 실행 결과<br>

시도 번호, 상태 코드, 응답 내용, 실행 타임스탬프를 포함하는 잡 실행 결과의 경량 표현입니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| tryNumber | int |  | ✓ |  | 1 ~ 10000 | 시도 횟수<br>이 실행 결과의 일련 시도 번호로, 1부터 시작합니다. 어느 재시도 시도가 이 결과를 생성했는지 식별하는 데 사용됩니다. |
| statusCode | int |  | ✓ |  | 0 ~ 1000 | 상태 코드<br>스크립트 실행에서 반환된 HTTP 상태 코드입니다. 2xx 코드는 성공을 나타내고, 그 외의 코드는 실패를 나타냅니다. 재시도 가능한 오류인 경우 maxTryCount에 도달하지 않았다면 자동으로 재시도가 이루어질 수 있습니다. |
| result | string |  | ✓ |  |  ~ 5242880자 | 응답 내용<br>스크립트 실행에서 반환된 JSON 형식의 응답 본문입니다. 성공 시에는 결과 데이터를, 실패 시에는 오류 상세 정보를 포함합니다. 최대 5MB입니다. |
| tryAt | long |  | ※ | 현재 시각 |  | 생성일시<br>UNIX 시간・밀리초<br>※ 서버가 자동으로 설정 |

**관련 메서드:**
run - 플레이어의 잡 큐에 있는 다음 잡을 실행한다


---

## 메서드

### run

플레이어의 잡 큐에 있는 다음 잡을 실행한다<br>

GS2에서는 즉시 완료하지 않아도 되는 처리를 '잡 큐'로 지연 실행합니다. 예를 들어 캐릭터를 입수했을 때 소지품 추가는 즉시 수행하지만, 도감 등록은 잡 큐를 통해 나중에 처리할 수 있습니다.<br>
이러한 구조 덕분에 관련 서비스가 일시적으로 중단되더라도 게임을 계속 진행할 수 있으며, 큐에 쌓인 잡은 서비스 복구 후 재시도되어 올바른 상태가 됩니다.<br>

이 API를 호출하면 플레이어의 큐에 있는 다음 잡을 하나 실행하고 그 결과를 반환합니다.<br>
응답에 포함된 `isLastJob` 플래그가 `false`인 경우 아직 처리되지 않은 잡이 남아 있으므로, `true`가 될 때까지 반복해서 호출하십시오.<br>

네임스페이스에 푸시 통지를 설정해 두면 새로운 잡이 추가되는 시점에 통지를 받을 수 있으므로, 폴링하지 않고 통지를 트리거로 삼아 이 API를 호출할 수도 있습니다.<br>

네임스페이스에서 `enableAutoRun`을 활성화한 경우에는 잡이 서버 측에서 자동으로 실행되므로, 이 API를 호출할 필요가 없습니다.

#### Request

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

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzJob](#ezjob) | 잡|
| result | [EzJobResultBody](#ezjobresultbody) | 잡 실행 결과 내용|
| isLastJob | bool | |

#### Error

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

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| ConflictException | ConflictException | 잡 큐 실행이 충돌했습니다. 재시도가 필요합니다. |

#### 구현 예제




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

```

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

```

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

```

**Godot**
```gdscript
# SDK 레벨에서 실행되므로 명시적으로 API를 호출할 필요는 없습니다

```


---

### getResult

완료된 잡의 실행 결과를 조회한다<br>

잡 이름을 지정하여 해당 잡의 실행 결과를 조회합니다.<br>
결과에는 성공·실패를 나타내는 상태 코드와 잡이 반환한 응답 내용이 포함됩니다.<br>

도감 등록이나 보상 배포 등 지연 처리가 올바르게 완료되었는지 확인하고 싶을 때 사용합니다.<br>
잡이 여러 번 재시도된 경우에는 시도 횟수를 지정하여 특정 시도의 결과를 확인할 수도 있습니다.<br>

※ 잡의 실행 결과는 실행 후 일정 기간 동안만 보관되며, 자동으로 삭제될 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| jobName | string |  | ✓| UUID |  ~ 36자 | 잡 이름<br>잡의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 각 잡을 식별하는 데 사용됩니다. |
| tryNumber | int |  | |  | 0 ~ 10000 | 시도 횟수 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzJobResult](#ezjobresult) | 잡 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.JobQueue.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Job(
        jobName: "job-0001"
    ).JobResult(
        tryNumber: null
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.JobQueue.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Job(
        jobName: "job-0001"
    ).JobResult(
        tryNumber: null
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->JobQueue->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Job(
        "job-0001" // jobName
    )->JobResult(
        nullptr // tryNumber
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.job_queue.namespace_(
        "namespace-0001"
    ).me(game_session).job(
        "job-0001"
    ).job_result(
        null
    )

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

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

```

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

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

```

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

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

```

**Godot**
```gdscript

var domain = ez.job_queue.namespace_(
        "namespace-0001"
    ).me(game_session).job(
        "job-0001"
    ).job_result(
        null
    )

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

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

---

## 이벤트 핸들러

### OnPushNotification

잡 큐에 잡이 등록되었을 때 사용하는 푸시 알림

 | 이름 | 타입 | 설명 |
| --- | --- | --- |
| namespaceName | string |네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.|
| userId | string |사용자ID|

#### 구현 예제





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

    gs2.JobQueue.OnPushNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
    };
```

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

    gs2.JobQueue.OnPushNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
    };
```

**Unreal Engine 5**
```cpp

    Gs2->JobQueue->OnPushNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto UserId = Notification->UserIdValue;
    });
```

**Godot**
```gdscript

    ez.job_queue.push_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var user_id = notification.user_id
    )
```


---

### OnRunNotification

잡 큐의 잡을 실행했을 때 사용하는 푸시 알림

 | 이름 | 타입 | 설명 |
| --- | --- | --- |
| namespaceName | string |네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.|
| userId | string |사용자ID|
| jobName | string |잡 이름<br>잡의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 각 잡을 식별하는 데 사용됩니다.|

#### 구현 예제





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

    gs2.JobQueue.OnRunNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var jobName = notification.JobName;
    };
```

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

    gs2.JobQueue.OnRunNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var userId = notification.UserId;
        var jobName = notification.JobName;
    };
```

**Unreal Engine 5**
```cpp

    Gs2->JobQueue->OnRunNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto JobName = Notification->JobNameValue;
    });
```

**Godot**
```gdscript

    ez.job_queue.run_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var user_id = notification.user_id
        var job_name = notification.job_name
    )
```


---



