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

# GS2-Guild

길드 기능



여러 플레이어가 팀을 만들어 함께 어떤 목표를 향해 활동할 수 있도록 하는 기능이 길드 기능입니다.
GS2-Guild는 길드 멤버의 관리와, 길드 멤버가 실행할 수 있는 권한 관리를 수행하기 위한 마이크로서비스입니다.

GS2-Guild에서 '길드'는 한 명의 플레이어로 취급되며, 길드 사용자라고 부릅니다.
길드 멤버는 길드 사용자로서 정보를 조회·갱신할 수 있는 페더레이션을 수행함으로써, 길드 멤버가 공통 프로퍼티를 조작할 수 있는 상태를 실현합니다.

예를 들어 `플레이어A`와 `플레이어B`가 소속되어 있는 `길드A`가 있다고 가정해 봅시다.
`플레이어 레벨`이나 `스태미나`와 같은 일반적인 정보가 `플레이어A`와 `플레이어B`에 연결되어 관리된다는 것은 쉽게 상상할 수 있을 것입니다.
이와 마찬가지로 `길드A`에 연결하여 `길드 레벨`과 같은 프로퍼티를 연결해서 관리하는 것도 쉽게 상상할 수 있을 것입니다.

GS2-Guild의 사상에서 특징적인 부분은, `플레이어A`, `플레이어B`와 `길드A` 사이에 명확한 구분이 없으며 모두 동일하게 `사용자`로 취급하여 처리한다는 점입니다.
그렇기 때문에 길드가 가지는 프로퍼티는 GS2의 모든 사용자 데이터를 다루는 마이크로서비스를 사용하여 관리할 수 있습니다.
예를 들어 길드에 GS2-Experience의 랭크·경험치를 부여할 수도 있고, GS2-Stamina의 스태미나를 부여할 수도 있으며, GS2-SkillTree의 스킬 트리를 부여할 수도 있습니다.

또한, GS2-Guild는 길드 멤버를 관리함과 동시에, 길드 멤버가 `길드 사용자`로서 GS2의 API를 호출할 수 있는 액세스 토큰을 발급하는 기능을 가지고 있습니다.
이때 길드 사용자로서 어떤 API를 호출할 수 있는지를 더욱 세밀하게 제어하기 위한 접근 권한 제어 기능이 있습니다.
이 기능을 이용하면 `길드 마스터` 직책을 가진 플레이어만이 길드 사용자로서 GS2-Showcase의 상품을 구매할 수 있도록 하는 기능을 구현할 수 있습니다.

## 길드 모델

길드 단위의 설정은 GuildModel로 관리합니다. `defaultMaximumMemberCount`와 `maximumMemberCount`로 멤버의 초기값과 상한을 정하고, `inactivityPeriodDays`에 길드 마스터의 비활동 기간을 지정하면 자동으로 후계자를 선출할 수 있습니다. `rejoinCoolTimeMinutes`로 탈퇴 후 재참가 쿨타임을, `maxConcurrentJoinGuilds`나 `maxConcurrentGuildMasterCount`로 동시 참가 길드 수나 길드 마스터 인원 제한도 설정할 수 있습니다.

## 길드 멤버

길드에 소속되어 있는 플레이어를 가리킵니다.

## 역할

길드에 소속된 플레이어의 직책에 해당하는 엔티티로, 실행 가능한 API의 종류를 정의합니다.
하나의 길드 모델에 최대 10종류의 역할을 정의할 수 있습니다.

### 권한 설정

역할에는 GS2-Identifier의 [정책 문서]()를 정의할 수 있습니다.
길드 사용자로 전환하기 전의 권한 && 역할의 권한 범위 내에서 API를 호출할 수 있습니다.

즉, 역할에 강력한 권한을 설정하더라도, 원래 길드 사용자로 접근하고 있을 때 호출할 수 없었던 API를 호출할 수 있게 되지는 않습니다.

#### 정책 문서 예시

*길드 마스터에 해당하는 최소한의 정책*

```json
{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Guild:Describe*",
        "Gs2Guild:Get*",
        "Gs2Guild:AcceptRequest",
        "Gs2Guild:RejectRequest",
        "Gs2Guild:DeleteMember",
        "Gs2Guild:DescribeIgnoreUsers",
        "Gs2Guild:AddIgnoreUser",
        "Gs2Guild:GetIgnoreUser",
        "Gs2Guild:DeleteIgnoreUser",
        "Gs2Gateway:SetUserId"
      ],
      "Resources": ["*"]
    }
  ]
}
```

*길드 사용자에 해당하는 최소한의 정책*

```json
{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Guild:Describe*",
        "Gs2Guild:Get*",
        "Gs2Guild:PromoteSeniorMember",
        "Gs2Gateway:SetUserId"
      ],
      "Resources": ["*"]
    }
  ]
}
```

#### 실전 예시

권한은 GS2-Identifier의 정책 문서 형식을 사용하여 정의합니다.
구체적인 예로, 길드 관리 권한과 길드 사용자의 GS2-Experience API를 호출하는 권한을 부여한다고 가정해 봅시다.

```json
{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Guild:Describe*",
        "Gs2Guild:Get*",
        "Gs2Guild:AcceptRequest",
        "Gs2Guild:RejectRequest",
        "Gs2Guild:DeleteMember",
        "Gs2Guild:DescribeIgnoreUsers",
        "Gs2Guild:AddIgnoreUser",
        "Gs2Guild:GetIgnoreUser",
        "Gs2Guild:DeleteIgnoreUser",
        "Gs2Gateway:SetUserId",
        "Gs2Experience:*"
      ],
      "Resources": ["*"]
    }
  ]
}
```

앞부분의 'Gs2Guild'로 시작하는 부분이 길드 사용자로서 실행 가능한 API를 선언하는 부분으로, 멤버 관리에 필요한 API가 지정되어 있습니다.
'Gs2Gateway:SetUserId'는 길드 사용자에 관한 알림을 수신할 수 있도록 하는 권한 설정입니다.
이 선언이 없으면 알림을 받을 수 없어, 길드 참가 신청이 도착한 것이나 길드 사용자에 관한 프로퍼티 변화를 앱이 알 수 없게 됩니다.
마지막의 'Gs2Experience:*'가 GS2-Experience의 모든 API를 호출할 수 있는 권한을 부여하는 부분입니다.

그런데 여기서 'Gs2Experience:*'라고 작성해 버리면, 'Gs2Experience:AddExperienceByUserId'와 같이 임의의 플레이어에게 임의의 경험치를 부여하는 API도 호출할 수 있게 되는 것은 아닐까 하고 불안하게 느껴질 수도 있습니다.
하지만 사용자 페더레이션을 할 경우, 페더레이션하기 전의 액세스 토큰이 가진 권한보다 더 강한 권한을 얻을 수는 없습니다.
따라서 일반적인 게임 플레이어가 가지고 있을 'ApplicationAccess' 권한으로는 원래 'Gs2Experience:AddExperienceByUserId'를 호출할 수 없으므로, 역할의 정책 문서에 모든 API를 호출할 수 있도록 기술하더라도 'Gs2Experience:AddExperienceByUserId'를 호출할 수 있게 되지는 않습니다.

GS2-Showcase에서 길드 마스터만이 길드 사용자로서 상품을 구매할 수 있도록 하고 싶다면, 길드 마스터의 역할에만 'Gs2Showcase:Buy'를 부여하는 방식으로 대응하면 세밀한 권한 관리가 가능합니다.

## 커스텀 역할

길드 고유의 역할입니다.
플레이어가 권한 조합을 자유롭게 정의하도록 하고 싶은 경우에 사용할 수 있습니다.

## 참가 인원

길드에는 참가 인원 제한을 설정할 수 있습니다.
참가 인원의 상한은 길드 단위로 인상할 수 있으며, 길드 레벨 상승과 함께 참가 인원 상한을 늘리는 구현도 가능합니다.

## 참가 방침

길드마다 참가 방침을 설정할 수 있습니다.
'자유 참가'와 '승인제'를 설정할 수 있습니다.

### 자유 참가

참가 리퀘스트를 보내면, 길드 멤버에 빈자리가 있는 경우 즉시 참가할 수 있습니다.

### 승인제

참가 리퀘스트를 보내도 곧바로 길드 멤버가 되지는 않습니다.
길드 멤버 중 승인 권한을 가진 플레이어의 승인을 받아야 길드 멤버가 될 수 있습니다.

## 길드 검색

### 길드 표시 이름

길드의 표시 이름으로 등록한 문자열의 부분 일치로 검색할 수 있습니다.

### 속성값

길드에는 최대 5종류의 속성값을 설정할 수 있습니다.
속성값은 정수값만 가능하며, 길드 검색 조건으로 사용할 수 있습니다.

길드를 검색할 때는 검색 조건으로 각 속성값에 대해 최대 10종류의 값으로 좁혀서 검색할 수 있습니다.
속성값을 대소 비교로 좁혀서 검색할 수는 없습니다.

검색 조건에 여러 속성값을 지정한 경우에는 AND 조건으로 검색됩니다. OR로 검색하는 방법은 없습니다.

### 멤버가 최대치에 도달한 길드를 검색 결과에 포함할지 여부

참/거짓 값으로 지정할 수 있습니다. true를 지정하면 멤버가 최대치에 도달한 길드도 검색 결과에 포함됩니다.
참고로, 멤버가 최대치에 도달한 길드에 대해서도 참가 리퀘스트를 보내는 것은 가능합니다.

### 검색 대상

검색 대상에는 지난 24시간 이내에 갱신된 길드만 포함됩니다.
이는 활성 상태가 아닌 길드를 대상에서 제외하면서, 검색에 필요한 비용을 최소화하려는 목적으로 이러한 사양으로 되어 있습니다.

길드 마스터는 특별히 변경 사항이 없더라도 하루에 한 번은 길드 정보를 갱신하도록 구현해 주십시오.

참고로, 갱신에는 멤버의 증감이나 역할 할당도 포함됩니다.

## 길드 참가 쿨다운

길드 참가 쿨다운 파라미터를 설정하면, 어딘가의 길드에서 탈퇴한 후 쿨다운으로 설정한 시간(분 단위)이 경과할 때까지 다른 길드에 참가 리퀘스트를 보낼 수 없습니다.

## 여러 길드 참가

플레이어는 여러 길드에 동시에 참가할 수 있습니다.
참가 가능한 길드 수에 제약을 두고 싶은 경우에는 애플리케이션에서 제어해 주십시오.

## 길드 마스터가 은퇴했을 때의 긴급 조치

유일한 길드 마스터가 아무런 예고 없이 은퇴해 버린 경우, 길드 유지가 어려워집니다.
이러한 상황에 빠졌을 때를 위한 긴급 조치를 마련해 두고 있습니다.

### 길드 마스터의 최종 활동 시간 조회

GetLastGuildMasterActivity 함수를 이용하면, 길드 마스터 역할을 보유한 플레이어가 마지막으로 Assume한 일시를 조회할 수 있습니다.
이 일시를 확인함으로써 길드 마스터 역할을 가진 '누가' '언제' 접근한 것이 마지막 접근인지를 판단할 수 있습니다.

### 긴급 조치 활성화 대기 일수

GuildModel에는 긴급 조치를 활성화하기 위해 대기해야 하는 일수를 정의할 수 있습니다.
길드 마스터의 최종 활동 시간으로부터 여기서 정한 일수가 경과하면 긴급 조치를 실행할 수 있게 됩니다.

### 긴급 조치 실행

긴급 조치의 실행은 PromoteSeniorMember를 호출하여 수행할 수 있습니다.
이 API를 호출하면 길드 멤버 중 참가 일시가 가장 오래된 플레이어를 새로운 길드 마스터로 승격시킵니다.
이때 최종 활동 시간도 승격된 플레이어가 활동한 것으로 갱신됩니다. 즉, 이 고참 멤버도 장기간 활동하지 않은 경우에는 추가로 일정 기간을 더 기다려야 합니다.

### 길드 마스터 교체 알림

GS2-Guild 자체에는 길드 마스터 교체에 관한 알림을 보내는 구조는 없습니다.
다만, 길드 멤버의 역할이 갱신되었을 때 실행되는 스크립트를 정의할 수 있으므로, 스크립트에서 길드 채팅에 메시지를 남기는 등의 추가 처리를 함으로써 길드 멤버가 길드 마스터 교체에 관한 정보를 알 수 있게 할 수 있습니다.

## 스크립트 트리거

네임스페이스에 `createGuildScript`·`updateGuildScript`·`joinGuildScript`·`receiveJoinRequestScript`·`leaveGuildScript`·`changeRoleScript`·`deleteGuildScript`를 설정하면, 길드 생성이나 갱신, 참가·탈퇴, 역할 변경 등 각 처리의 전후에 커스텀 스크립트를 실행할 수 있습니다. 스크립트는 동기 실행뿐만 아니라 Amazon EventBridge를 이용한 비동기 실행도 선택할 수 있습니다.

설정할 수 있는 주요 이벤트 트리거와 스크립트 설정 이름은 다음과 같습니다.

- `createGuildScript`(완료 알림: `createGuildDone`): 길드 생성 전후
- `updateGuildScript`(완료 알림: `updateGuildDone`): 길드 정보 갱신 전후
- `joinGuildScript`(완료 알림: `joinGuildDone`): 길드 참가 전후
- `receiveJoinRequestScript`(완료 알림: `receiveJoinRequestDone`): 참가 리퀘스트 접수 전후
- `leaveGuildScript`(완료 알림: `leaveGuildDone`): 길드 탈퇴 전후
- `changeRoleScript`(완료 알림: `changeRoleDone`): 역할 변경 전후
- `deleteGuildScript`(완료 알림: `deleteGuildDone`): 길드 삭제 전후

## 푸시 알림
설정할 수 있는 주요 푸시 알림과 설정 이름은 다음과 같습니다.

- `changeNotification`: 길드 정보 변경 시 알림
- `joinNotification`: 멤버 참가 시 알림
- `leaveNotification`: 멤버 탈퇴 시 알림
- `changeMemberNotification`: 멤버 정보 변경 시 알림
- `receiveRequestNotification`: 참가 리퀘스트 접수 시 알림
- `removeRequestNotification`: 참가 리퀘스트 삭제 시 알림

모두 GS2-Gateway를 경유하여 리얼타임으로 알릴 수 있으며, 오프라인 단말로의 모바일 푸시 전달도 지정할 수 있습니다.

## 트랜잭션 액션

GS2-Guild에서는 다음과 같은 트랜잭션 액션을 제공하고 있습니다.

- 검증 액션: 길드 멤버 포함 여부 확인(특정 사용자가 멤버인지), 최대 참가 가능 인원 검증
- 소비 액션: 최대 참가 가능 인원 감산
- 획득 액션: 최대 참가 가능 인원 가산, 최대 참가 가능 인원 설정

'길드 멤버 포함 여부 확인'을 검증 액션으로 이용함으로써, 특정 길드에 소속된 멤버만 받을 수 있는 보상이나, 특정 길드 멤버가 아닌 경우에만 실행 가능한 처리와 같은 제한을 트랜잭션 안에 포함시킬 수 있습니다. 이를 통해 길드 대항 이벤트의 보상 배포나, 길드 미소속자 한정 권유 캠페인 등을 안전하게 구현할 수 있습니다.

## 마스터 데이터 운용
마스터 데이터를 등록함으로써 마이크로서비스에서 이용 가능한 데이터와 동작을 설정할 수 있습니다.

마스터 데이터의 종류에는 다음과 같은 것이 있습니다.

- `GuildModel`: 멤버 상한이나 재참가 쿨타임 등의 설정
- `RoleModel`: 길드 내 권한을 정의하는 역할

마스터 데이터 등록은 관리 콘솔에서 등록하는 것 외에도, GitHub에서 데이터를 반영하거나 GS2-Deploy를 사용하여 CI에서 등록하는 워크플로우를 구성하는 것도 가능합니다.

## 구현 예제

### 길드 생성



**Unity**
```csharp

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CreateGuildAsync(
        guildModelName: "guild-model-0001",
        displayName: "My Guild",
        joinPolicy: "anybody",
        attribute1: 1,
        attribute2: null,
        attribute3: null,
        attribute4: null,
        attribute5: null,
        customRoles: null,
        guildMemberDefaultRole: null
    );
    var item = await result.ModelAsync();
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->CreateGuild(
        "guild-model-0001", // guildModelName
        "My Guild", // displayName
        "anybody", // joinPolicy
        1, // attribute1
        TOptional<int32>(), // attribute2
        TOptional<int32>(), // attribute3
        TOptional<int32>(), // attribute4
        TOptional<int32>(), // attribute5
        nullptr, // customRoles
        TOptional<FString>() // guildMemberDefaultRole
    );
    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();
```
**Godot**
```gdscript

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

var async_result = await domain.create_guild(
    "guild-model-0001", # guild_model_name
    "My Guild", # display_name
    "anybody", # join_policy
    1, # attribute1
    null, # attribute2
    null, # attribute3
    null, # attribute4
    null, # attribute5
    null, # metadata
    null, # member_metadata
    null, # custom_roles
    null # guild_member_default_role
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


### 길드 검색



**Unity**
```csharp

    var items = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SearchGuildsAsync(
        guildModelName: "guild-model-0001",
        displayName: "My Guild",
        attributes1: new int[] { 0, 1 },
        attributes2: null,
        attributes3: null,
        attributes4: null,
        attributes5: null,
        joinPolicies: null,
        includeFullMembersGuild = null
    ).ToListAsync();
```
**Unreal Engine**
```cpp

    const auto It = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SearchGuilds(
        "guild-model-0001", // guildModelName
        "My Guild", // displayName
        MakeShared<TArray<int32>>([]{
            TArray<int32> v;
            v.Add(0);
            v.Add(1);
            return v;
        }()), // attributes1
        TSharedPtr<TArray<int32>>(), // attributes2
        TSharedPtr<TArray<int32>>(), // attributes3
        TSharedPtr<TArray<int32>>(), // attributes4
        TSharedPtr<TArray<int32>>(), // attributes5
        TSharedPtr<TArray<FString>>(), // joinPolicies
        TOptional<bool>(true) // includeFullMembersGuild
    );
    TArray<Gs2::UE5::Guild::Model::FEzGuildPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
```
**Godot**
```gdscript

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

var async_result = await domain.search_guilds(
    "guild-model-0001", # guild_model_name
    null, # display_name
    null, # attributes1
    null, # attributes2
    null, # attributes3
    null, # attributes4
    null, # attributes5
    null, # join_policies
    null, # include_full_members_guild
    null # order_by
).load()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


### 길드에 참가 리퀘스트 전송

길드의 참가 방침이 '자유 참가'인 경우에는 즉시 길드 멤버가 됩니다



**Unity**
```csharp

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestAsync(
        guildModelName: "guild-0002",
        targetGuildName: "guild-0002"
    );
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SendRequest(
        "guild-0002", // guildModelName
        "guild-0002" // targetGuildName
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
```
**Godot**
```gdscript

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

var async_result = await domain.send_request(
    "guild-0002", # guild_model_name
    "guild-0002", # target_guild_name
    null # metadata
)
if async_result.error != null:
    if async_result.error.type == "MaximumMembersReachedException":
        # 멤버 수가 상한에 도달했습니다.
        pass
    if async_result.error.type == "MaximumJoinedGuildsReachedException":
        # 동시에 참가할 수 있는 길드 수가 최대값에 도달했습니다.
        pass
    if async_result.error.type == "MaximumReceiveRequestsReachedException":
        # 길드에 대한 참가 리퀘스트 수가 상한에 도달했습니다.
        pass
    if async_result.error.type == "MaximumSendRequestsReachedException":
        # 자신이 보낸 참가 리퀘스트 수가 상한에 도달했습니다.
        pass
    if async_result.error.type == "DotMeetJoinRequirementsException":
        # 길드 참가 조건을 충족하지 않습니다.
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


### 전송한 참가 리퀘스트 목록 조회



**Unity**
```csharp

    var items = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestsAsync(
        guildModelName: "guild-0002"
    ).ToListAsync();
```
**Unreal Engine**
```cpp

    const auto It = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->SendRequests(
        "guild-0002" // guildModelName
    );
    TArray<Gs2::UE5::Guild::Model::FEzSendMemberRequestPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
```
**Godot**
```gdscript

var iterator = ez.guild.namespace_(
        "namespace-0001"
    ).me(
        game_session
    ).send_requests(
        "guild-0002"
    )

var async_result = await iterator.load()
if async_result.error != null:
    # 오류 처리
    push_error(str(async_result.error))
    return

var items = async_result.result

```


### 참가 리퀘스트 철회



**Unity**
```csharp

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CancelRequestAsync(
        guildModelName: "guild-0002",
        targetGuildName: "guild-0002"
    );
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->CancelRequest(
        "guild-0002", // guildModelName
        "guild-0002" // targetGuildName
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();
```
**Godot**
```gdscript

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

var async_result = await domain.cancel_request(
    "guild-0002", # guild_model_name
    "guild-0002" # target_guild_name
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


### 길드 사용자로서 접근하기 위한 게임 세션 취득



**Unity**
```csharp

    var guildGameSession = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).AssumeAsync(
        guildModelName: "guild-model-0001",
        guildName: "guild-0001"
    );
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Assume(
        "guild-model-0001", // guildModelName
        "guild-0001" // guildName
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto GuildGameSession = Future->GetTask().Result();
```
**Godot**
```gdscript

var domain = ez.guild.namespace_(
    "namespace-0001"
).me(game_session)
var async_result = await domain.assume(
    "gateway-namespace-0001", false, "guild-model-0001", "guild-0001"
)
if async_result.error != null:
    push_error(str(async_result.error))
    return
var guild_game_session = async_result.result

```


### 수신한 참가 리퀘스트 목록 조회



**Unity**
```csharp

    var domain = gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).GuildGameSession(
        guildModelName: "guild-0001",
        guildGameSession: guildGameSession
    );
    var items = await domain.ReceiveRequestsAsync(
    ).ToListAsync();
```
**Unreal Engine**
```cpp

    const auto It = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    )->ReceiveRequests(
    );
    TArray<Gs2::UE5::Guild::Model::FEzReceiveMemberRequestPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
```
**Godot**
```gdscript

var iterator = ez.guild.namespace_(
        "namespace-0001"
    ).guild_game_session(
        "guild-0001",
        guild_game_session
    ).receive_requests(
    )

var async_result = await iterator.load()
if async_result.error != null:
    # 오류 처리
    push_error(str(async_result.error))
    return

var items = async_result.result

```


### 참가 리퀘스트 승인



**Unity**
```csharp

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    ).ReceiveMemberRequest(
        fromUserId: "user-0001"
    ).AcceptRequestAsync(
    );
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    )->ReceiveMemberRequest(
        "user-0001" // fromUserId
    )->AcceptRequest(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();
```
**Godot**
```gdscript

var domain = ez.guild.namespace_(
    "namespace-0001"
).guild_game_session(
    "guild-0001", guild_game_session
).receive_member_request("user-0001")
var async_result = await domain.accept_request()
if async_result.error != null:
    push_error(str(async_result.error))
    return

```


### 참가 리퀘스트 거부



**Unity**
```csharp

    var result = await gs2.Guild.Namespace(
        namespaceName: "namespace-0001"
    ).GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    ).ReceiveMemberRequest(
        fromUserId: "user-0001"
    ).RejectRequestAsync(
    );
```
**Unreal Engine**
```cpp

    const auto Future = Gs2->Guild->Namespace(
        "namespace-0001" // namespaceName
    )->GuildGameSession(
        "guild-0001", // guildModelName
        GuildGameSession // guildGameSession
    )->ReceiveMemberRequest(
        "user-0001" // fromUserId
    )->RejectRequest(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();
```
**Godot**
```gdscript

var domain = ez.guild.namespace_(
    "namespace-0001"
).guild_game_session(
    "guild-0001", guild_game_session
).receive_member_request("user-0001")
var async_result = await domain.reject_request()
if async_result.error != null:
    push_error(str(async_result.error))
    return

```


## 상세 레퍼런스

[GS2-Guild API 레퍼런스](../../api_reference/guild)



