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

# GS2-LoginReward 트랜잭션 액션

검증/소비/입수 각 트랜잭션 액션의 사양




## 액션의 조합과 동시 실행

모든 서비스에 공통되는 전제는 [트랜잭션 액션의 조합]()에 정리되어 있습니다. 먼저 그쪽을 읽어 주십시오. 이 절의 나머지는 GS2-LoginReward 고유의 내용입니다.

GS2-LoginReward의 트랜잭션 액션은 네임스페이스·사용자·보너스 모델의 조합으로 결정되는 하나의 수령 상황을 대상으로 합니다. 어떤 스텝을 수령했는지를 목록을 통째로 가지는 한 행으로 기록합니다.

조작 | 같은 행을 겹쳤을 때 | 중첩 너머 | 다른 대상이 되는 경계 | 직렬 실행 모드 활성화 시
--- | --- | --- | --- | ---
스텝의 수령 완료 마크<br>`MarkReceivedByUserId` | **같은 스텝이면 하나로 합쳐짐. 스텝이 다르면 오류 (400)** | 같은 스텝이면 통과. 스텝이 다르면 실패한다 | 네임스페이스·사용자·보너스 모델 | 스텝이 달라도 성립한다. 나중에 실행된 쪽이 이미 기록된 목록을 읽은 뒤 자신의 스텝을 추가하므로 양쪽 스텝이 모두 마크된다
마크의 취소<br>`UnmarkReceivedByUserId` | **같은 스텝이면 하나로 합쳐짐. 스텝이 다르면 오류 (400)** | 같은 스텝이면 통과. 스텝이 다르면 실패한다 | 네임스페이스·사용자·보너스 모델 | 스텝이 달라도 성립한다. 나중에 실행된 쪽이 이미 기록된 목록을 읽은 뒤 자신의 스텝을 제거하므로 양쪽 취소가 모두 반영된다
수령 상황의 파기<br>`DeleteReceiveStatusByUserId` | 1건으로 통합된다 | 실패한다 | 네임스페이스·사용자·보너스 모델 | 중첩을 넘어서도 성립한다. 1건으로 통합되지는 않지만, 이미 파기된 수령 상황을 다시 파기하는 경우에는 새로 만든 뒤 파기할 뿐이다

**여러 스텝을 하나의 트랜잭션에서 수령하지 마십시오.** 수령 완료 스텝의 목록은 한 행에 모여 있어 전체가 다시 쓰이므로, 경계를 스텝 단위로 나눌 수 없습니다. 그 때문에 다른 스텝에 대한 마크를 두 개 나열하면 합성할 수 없어, 트랜잭션을 구성하는 시점에 오류 (400) 가 됩니다. 같은 스텝에 대한 마크는 하나로 합쳐집니다. 스텝별로 트랜잭션을 나누어 주십시오.

마크와 그 취소는 행이 다르고 경계가 같습니다. 하나의 트랜잭션에서 마크와 취소를 수행할 수는 없습니다. 스텝 보상의 수령은 마크로 표현되며, 그 마크를 근거로 보상이 지급됩니다.

수령 상황의 파기는 내용을 바꾸는 것이 아니라 통째로 지우므로, 그것을 건드리는 다른 액션과 함께 둘 수 없습니다.

### 중첩된 트랜잭션에 주의

안쪽에서 마크된 스텝과 바깥쪽에서 건드려진 같은 수령 상황이 충돌하여 트랜잭션이 실패합니다. 하나의 트랜잭션 안이든 중첩 너머든, 다른 스텝에 대한 마크는 모두 오류가 됩니다.

직렬 실행 모드(`enableSequentialExecution` 또는 `TransactionSettingV2`)를 활성화하면 중첩을 넘어선 이 실패는 일어나지 않습니다. 안쪽 트랜잭션이 바깥쪽과 같은 직렬 실행 구간에서 실행되므로, 나중에 실행된 쪽이 먼저 실행된 쪽이 이미 기록한 목록을 읽은 뒤 자신의 스텝을 반영하여 양쪽 스텝이 모두 결과에 남습니다. 하나의 트랜잭션 안에서 다른 스텝에 대한 마크를 두 개 넣는 제약은 변하지 않습니다. 이는 액션이 실행되기 전 조립 시점의 검사이므로 실행 모드의 영향을 받지 않습니다.

### 제한을 회피하고 싶은 경우

수령 완료 마크는 소비 액션, 그 취소와 수령 상황의 파기는 획득 액션입니다. 취소와 파기의 충돌은 `acquireActionUseJobQueue`를 활성화하면 해소되지만, 마크와의 공존은 `enableAtomicCommit`을 비활성화하지 않으면 해소되지 않습니다. 다만 하나의 트랜잭션에 다른 스텝의 마크를 넣은 경우는 어느 설정으로도 허용되지 않습니다. 트랜잭션을 구성하는 시점에 거부되기 때문입니다.

### 동시 실행과 재시도

수령 상황은 리비전 대조를 수반하여 전체가 다시 쓰이므로, 같은 수령 상황에 대한 동시 업데이트가 있으면 나중에 확정된 쪽이 충돌(409)이 됩니다. 요청 내용에 문제가 있는 것은 아니므로, 재시도하면 성공합니다.

---



## Consume Action

소비 액션

### Gs2LoginReward:MarkReceivedByUserId

사용자 ID를 지정하여 수령 완료 처리<br>

지정된 사용자의 보너스 모델에서 특정 스텝을 수동으로 수령 완료로 표시합니다.

**수량 지정 가능한 액션: 아니오**

**반전 가능한 액션: 예**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| bonusModelName | string |  | ✓|  |  ~ 128자 | 보너스 모델 이름<br>이 수신 상태가 연결된 로그인 보너스 모델의 이름.<br>사용자의 수신 진행 상황을 특정 보너스 모델 정의와 연결하여, 어떤 보상 목록과 배포 규칙이 적용되는지를 결정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| stepNumber | int |  | ✓|  | 0 ~ 100 | 스텝 번호 |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2LoginReward:MarkReceivedByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "bonusModelName": "[string]보너스 모델 이름",
        "userId": "[string]사용자ID",
        "stepNumber": "[int]스텝 번호",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2LoginReward:MarkReceivedByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  bonusModelName: "[string]보너스 모델 이름"
  userId: "[string]사용자ID"
  stepNumber: "[int]스텝 번호"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("loginReward").consume.mark_received_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    bonusModelName="[string]보너스 모델 이름",
    userId="[string]사용자ID",
    stepNumber="[int]스텝 번호",
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---

## Acquire Action

입수 액션

### Gs2LoginReward:DeleteReceiveStatusByUserId

사용자 ID를 지정하여 수령 상태 리셋<br>

지정된 사용자의 보너스 모델의 수령 상태 데이터를 모두 삭제하여 보너스 진행 상황을 완전히 리셋합니다.

**수량 지정 가능한 액션: 아니오**

**반전 가능한 액션: 아니오**

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




**JSON**
```json
{
    "action": "Gs2LoginReward:DeleteReceiveStatusByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "bonusModelName": "[string]보너스 모델 이름",
        "userId": "[string]사용자ID",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2LoginReward:DeleteReceiveStatusByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  bonusModelName: "[string]보너스 모델 이름"
  userId: "[string]사용자ID"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("loginReward").acquire.delete_receive_status_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    bonusModelName="[string]보너스 모델 이름",
    userId="[string]사용자ID",
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---

### Gs2LoginReward:UnmarkReceivedByUserId

사용자 ID를 지정하여 미수령 처리<br>

지정된 사용자의 보너스 모델에서 수령 완료로 표시된 스텝을 미수령 상태로 되돌립니다.<br>
지정된 스텝이 수령 완료 상태가 아닌 경우, 오류가 반환됩니다.

**수량 지정 가능한 액션: 아니오**

**반전 가능한 액션: 예**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| bonusModelName | string |  | ✓|  |  ~ 128자 | 보너스 모델 이름<br>이 수신 상태가 연결된 로그인 보너스 모델의 이름.<br>사용자의 수신 진행 상황을 특정 보너스 모델 정의와 연결하여, 어떤 보상 목록과 배포 규칙이 적용되는지를 결정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| stepNumber | int |  | ✓|  | 0 ~ 100 | 스텝 번호 |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2LoginReward:UnmarkReceivedByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "bonusModelName": "[string]보너스 모델 이름",
        "userId": "[string]사용자ID",
        "stepNumber": "[int]스텝 번호",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2LoginReward:UnmarkReceivedByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  bonusModelName: "[string]보너스 모델 이름"
  userId: "[string]사용자ID"
  stepNumber: "[int]스텝 번호"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("loginReward").acquire.unmark_received_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    bonusModelName="[string]보너스 모델 이름",
    userId="[string]사용자ID",
    stepNumber="[int]스텝 번호",
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---



