GS2-Buff
GS2-Buff는 GS2가 제공하는 마이크로서비스의 대가와 보상, 사용자 데이터 최대값의 보정을 일원화하여 관리하는 기능을 제공합니다. 기간 한정으로 보상을 증가시키는 기능이나, 구독 계약 상태라면 사용자 데이터의 최대값이 증가하는 기능을 구현할 때 활용할 수 있습니다.
GS2-Buff는 다른 마이크로서비스를 직접 수정하는 것이 아니라, API 호출 시 전달되는 “컨텍스트 스택"이라는 메타 정보를 통해 각 마이크로서비스에 보정값을 전파합니다. 따라서 버프의 내용이나 기간을 변경하더라도 각 마이크로서비스의 마스터 데이터나 플레이어 데이터를 전혀 수정하지 않고도 적용·해제가 가능하다는 점이 큰 특징입니다.
사용 사례
GS2-Buff가 상정하는 대표적인 사용 사례는 다음과 같습니다.
- 기간 한정으로 경험치 획득량을 2배로 만드는 캠페인
- 특정 쇼케이스에서 판매되는 상품 가격을 일괄 20% 할인
- 구독 계약 중에는 스태미나 최대값을 상향
- 특정 장비를 장착 중일 때만 퀘스트 보상을 증가
- 이벤트 기간 동안에만 강화 소재 소비량을 절반으로 감소
graph LR Player["플레이어"] -->|ApplyBuff| Buff[GS2-Buff] Buff -->|컨텍스트 스택| Player Player -->|API + 컨텍스트 스택| Other["다른 마이크로서비스<br/>(GS2-Experience / GS2-Stamina / GS2-Showcase 등)"] Other -.참조.-> Buff Other -->|보정 후 값| Player
마스터 데이터 관리
마스터 데이터를 등록하면 마이크로서비스에서 이용 가능한 데이터와 동작을 설정할 수 있습니다.
마스터 데이터의 종류에는 다음이 있습니다.
BuffEntryModel: 보정값과 대상을 정의하는 기본 모델
마스터 데이터 등록은 관리 콘솔에서 등록하는 방법 외에도, GitHub에서 데이터를 반영하거나 GS2-Deploy를 사용해 CI에서 등록하는 워크플로우를 구성할 수도 있습니다.
BuffEntryModel의 주요 설정 항목
| 설정 항목 | 설명 |
|---|---|
name | 버프를 식별하는 고유한 이름 |
metadata | 클라이언트 측에서 이용하는 임의의 메타데이터 |
expression | 보정 계산식의 종류 (Rate Add / Mul / Value Add) |
targetType | 보정 대상이 “모델"인지 “액션"인지 |
targetModel / targetAction | 보정 대상의 모델명·액션명·조건 GRN·보정 레이트 |
priority | 적용 우선순위. 값이 작은 것부터 순서대로 계산 |
applyPeriodScheduleEventId | GS2-Schedule 이벤트에 의한 유효 기간 |
버프 엔티티
각 마이크로서비스에 가하는 보정의 단위입니다. 기초값을 1.0으로 하여, 각 파라미터에 대해 어느 정도 증감시킬지를 정의합니다.
이용 가능한 주요 버프 종류와 계산 방법은 다음과 같습니다.
Rate Add: 보정 레이트에 가산Mul: 보정 레이트에 승산Value Add: 값을 직접 가산 (모델이나 액션의 수치에만 해당)
Rate Add와 Mul은 보정 레이트에 대한 연산으로, Rate Add 1.5로 설정하면 보정값은 2.5배가 되고, Mul 1.5로 설정하면 보정값은 1.5배가 됩니다. Value Add는 값을 직접 가산하는 연산으로, Value Add 5로 설정하면 보정값은 +5가 됩니다.
적용 우선순위
보정값에는 적용 우선순위를 설정할 수 있습니다. 우선순위에 설정된 값이 작은 보정값부터 순서대로 보정값 계산이 이루어집니다. 예를 들어, 다음과 같은 보정값이 정의되어 있다고 가정합니다.
| 보정값 종류 | 보정값 | 적용 우선순위 |
|---|---|---|
| Rate Add | 0.2 | 1 |
| Mul | 1.5 | 2 |
| Rate Add | 0.2 | 3 |
이 경우, 다음 순서로 보정값 계산이 실행됩니다.
1.0 + 0.2 = 1.2
1.2 * 1.5 = 1.8
1.8 + 0.2 = 2.0그리고 최종 보정값은 2.0배가 됩니다.
Value Add가 포함된 보정 계산
보정값 중에 “Value Add"가 포함되어 있는 경우, “Value Add"가 정의된 우선순위의 직전까지 보정 계산을 먼저 수행하고, 계산 후의 값에 대해 값 가산이 이루어집니다.
| 보정값 종류 | 보정값 | 적용 우선순위 |
|---|---|---|
| Rate Add | 0.2 | 1 |
| Mul | 1.5 | 2 |
| Value Add | 2 | 3 |
| Rate Add | 0.2 | 4 |
이 경우, 먼저 Value Add가 나타나기 직전까지의 보정값 계산이 실행됩니다.
1.0 + 0.2 = 1.2
1.2 * 1.5 = 1.8그리고 입력값에 일단 이 보정값을 적용합니다. 예를 들어 입력이 10이라면 1.8배를 하여 보정 후의 값은 18이 됩니다. 보정 후의 값에 “Value Add"의 +2가 적용되어, 보정 후의 값은 20이 됩니다.
이어서 Value Add가 나타난 직후부터의 보정값 계산이 실행됩니다.
1.0 + 0.2 = 1.2그리고 입력값에 일단 이 보정값을 적용합니다. 입력이 10이라면 1.2배를 하여 보정 후의 값은 12가 됩니다. “Value Add” 이후의 보정값에 이 값을 가산합니다.
20 + 12 = 32이렇게 해서 입력이 10인 경우 최종 보정 후의 값은 32가 됩니다.
전체 식을 정리하면 다음과 같습니다. 입력값을 x로 표기합니다.
((x * (1.0 + 0.2) * 1.5) + 2) + x * (1.0 + 0.2)보정 대상 설정
버프에 의한 보정 대상은 크게 2종류로, “모델"과 “액션"이 있습니다. 어떤 모델이나 액션을 설정할 수 있는지는 각 마이크로서비스의 버프 관련 문서를 참조하십시오.
모델
모델의 적용 대상 예시로는 다음과 같은 것이 있습니다.
- GS2-Experience의 랭크 캡
- GS2-Stamina의 스태미나 최대값
- GS2-Showcase의 획득 액션
- GS2-Showcase의 소비 액션
액션
액션의 적용 대상 예시로는 다음과 같은 것이 있습니다.
- GS2-Experience의 경험치 가산량
- GS2-Stamina의 스태미나 회복량
- GS2-Stamina의 스태미나 소비량
보정 적용 조건 설정
GS2-Showcase에 적용한다면 어느 DisplayItem에 보정값을 적용할 것인가? GS2-Experience에 적용한다면 어느 Status에 보정값을 적용할 것인가? 와 같은 적용 조건을 설정하는 것이 이 파라미터입니다.
각 버프에 대해 어떤 적용 조건을 설정할 수 있는지는 각 마이크로서비스의 버프 관련 문서를 참조하십시오.
모델과 GRN
적용 조건에는 모델과 GRN을 지정합니다. 버프에 따라서는 여러 모델을 지정할 수 있는 경우도 있습니다. 예를 들어 GS2-Showcase의 경우, Showcase 내의 모든 DisplayItem에 보정을 적용하기 위해 Showcase의 GRN을 지정하는 패턴과, Showcase 내의 특정 DisplayItem에만 보정을 적용하기 위해 DisplayItem의 GRN을 지정하는 패턴이 있습니다.
버프에는 여러 적용 조건을 설정할 수 있으며, 그중 어느 하나라도 해당되면 보정값이 적용됩니다. 즉, 하나의 버프 엔티티에 여러 DisplayItem을 적용 조건으로 설정함으로써, 하나의 버프 엔티티로 여러 DisplayItem에 대한 보정값을 정의할 수 있습니다.
보정 적용 방법
GS2-Buff의 ApplyBuff API를 호출하면 “컨텍스트 스택"이 응답으로 반환됩니다. GS2가 제공하는 모든 API에는 컨텍스트 스택을 지정할 수 있는 인터페이스가 마련되어 있습니다. GS2-Buff가 응답한 컨텍스트 스택을 각 API 호출 시 지정함으로써 버프를 적용할 수 있습니다.
게임 엔진용 SDK와 같은 상위 레벨 SDK에서는 컨텍스트 스택 지정이 래핑되어 있어 명시적으로 지정할 필요가 없는 경우가 있습니다.
sequenceDiagram participant Player as 플레이어 participant Buff as GS2-Buff participant Other as 다른 마이크로서비스 Player->>Buff: ApplyBuff Buff-->>Player: 컨텍스트 스택 Player->>Other: API 호출 (컨텍스트 스택 부여) Other-->>Player: 버프가 적용된 값
보정 적용 범위
버프의 적용 범위는 광범위하여, 마스터 데이터 취득 API에도 버프가 적용됩니다. 컨텍스트 스택을 지정한 상태로 마스터 데이터 취득 API를 호출하면, 버프가 적용된 상태의 값이 응답됩니다. 게임 내에서 버프가 적용되지 않은 상태의 값을 함께 표시하고 싶은 경우, 컨텍스트 스택을 부여하지 않은 API 접근을 조합하여 표시해야 합니다.
버프 엔티티와 GS2-Schedule의 연계
컨텍스트 스택 내의 버프 정보는 유효 기간을 보유합니다. 즉, 버프 엔티티에 유효 기간으로 GS2-Schedule의 이벤트가 설정되어 있는 경우, 이벤트 기간 밖이 되면 자동으로 버프가 적용되지 않게 됩니다.
단, 새롭게 버프의 적용 조건이 변경되거나 새로운 버프가 추가된 경우에는 다시 ApplyBuff를 호출하여 버프를 반영해야 합니다.
컨텍스트 스택의 유효 기한
컨텍스트 스택에는 유효 기한이 설정되어 있습니다. ApplyBuff를 호출한 시점으로부터 24시간이 경과하면 컨텍스트 스택은 효력을 잃습니다.
ApplyBuff는 조건에 변경이 없더라도 24시간 이내에 다시 실행하도록 하십시오.
스크립트에 의한 레이트 오버라이드
applyBuffScript의 동기 스크립트 반환값으로 OverrideBuffRate (name과 rate의 쌍)를 반환함으로써, 버프 적용 시 해당 버프의 레이트를 동적으로 오버라이드할 수 있습니다.
플레이어의 상태나 시간대, 보유 장비에 따라 버프의 레이트를 세밀하게 변동시키고 싶은 경우에 활용할 수 있습니다.
스크립트 트리거
버프 적용 전후에 GS2-Script를 호출하는 이벤트 트리거를 설정할 수 있습니다. 트리거는 동기·비동기 실행 방식을 선택할 수 있으며, doneTriggerTargetType을 통해 Amazon EventBridge 등으로의 완료 알림도 가능합니다.
설정 가능한 주요 이벤트 트리거와 스크립트 설정명은 다음과 같습니다.
applyBuffScript(완료 알림:applyDone): 버프 적용 전후. 스크립트의 반환값으로 버프의 적용 레이트를 동적으로 오버라이드하는 것도 가능합니다.
구현 예제
버프를 적용
ApplyBuff를 호출하면, Gs2 객체 자체가 버프 적용 후의 컨텍스트를 보유한 새로운 인스턴스로 전환됩니다. 반환된 Gs2 객체를 이후의 접근에서 사용함으로써, 버프가 적용된 상태로 각 마이크로서비스를 이용할 수 있습니다.
var domain = gs2.Buff.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Buff();
gs2 = await domain.ApplyBuffAsync();
// 새로운 gs2 오브젝트를 통해 접근하면 버프가 적용된 값으로 처리됩니다 const auto Domain = Gs2->Buff->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Buff(
);
const auto Future = Domain->ApplyBuff(
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
// obtain changed values / result values
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError())
{
return Future2->GetTask().Error();
}
const auto Result = Future2->GetTask().Result();
// 새로운 Gs2 오브젝트를 통해 접근하면 버프가 적용된 값으로 처리됩니다
var domain = ez.buff.namespace_(
"namespace-0001"
).me(game_session).buff(
)
var async_result = await domain.apply_buff(
)
if async_result.error != null:
push_error(str(async_result.error))
return
var result = async_result.result등록된 버프 엔티티 목록 취득
게임 내 캠페인 목록 표시 등을 위해, 현재 등록되어 있는 버프 엔티티를 취득할 수 있습니다.
var items = await gs2.Buff.Namespace(
namespaceName: "namespace-0001"
).BuffEntryModelsAsync(
).ToListAsync(); const auto It = Gs2->Buff->Namespace(
"namespace-0001" // namespaceName
)->BuffEntryModels();
TArray<Gs2::UE5::Buff::Model::FEzBuffEntryModelPtr> Result;
for (auto Item : *It)
{
if (Item.IsError())
{
return false;
}
Result.Add(Item.Current());
}var iterator = ez.buff.namespace_(
"namespace-0001"
).buff_entry_models(
)
var async_result = await iterator.load()
if async_result.error != null:
# 에러를 처리
push_error(str(async_result.error))
return
var items = async_result.result특정 버프 엔티티 취득
var item = await gs2.Buff.Namespace(
namespaceName: "namespace-0001"
).BuffEntryModel(
buffEntryName: "buff-0001"
).ModelAsync(); const auto Domain = Gs2->Buff->Namespace(
"namespace-0001" // namespaceName
)->BuffEntryModel(
"buff-0001" // buffEntryName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;
const auto Item = Future->GetTask().Result();var domain = ez.buff.namespace_(
"namespace-0001"
).buff_entry_model(
"character-level"
)
var async_result = await domain.model()
if async_result.error != null:
push_error(str(async_result.error))
return
var result = async_result.result다른 마이크로서비스와의 조합
GS2-Buff는 단독으로 사용하는 것이 아니라 다른 마이크로서비스와 조합하여 이용합니다. 주요 연계 대상과 그에 대응하는 보정 대상의 예시는 다음과 같습니다.
| 연계 대상 | 보정 대상 예시 |
|---|---|
| GS2-Experience | 경험치 획득량, 랭크 캡 |
| GS2-Stamina | 스태미나 최대값, 회복량, 소비량 |
| GS2-Showcase | DisplayItem의 판매 가격, 획득 수량 |
| GS2-Money2 | 입금량, 소비량 |
| GS2-Inventory | 아이템 획득 수량 |
| GS2-Quest | 퀘스트 보상 획득 수량 |
| GS2-Enhance | 강화 소재 소비 수 |
각 마이크로서비스가 어떤 모델명·액션명에 대한 버프를 받아들이는지는 각 마이크로서비스의 문서를 참조하십시오.