---
id: wiki-2026-0508-alliance-동맹
title: Alliance (동맹)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Guild, Clan, Faction, 동맹]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [game-design, social-systems, mmo, architecture]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: typescript
  framework: Game backend (Colyseus, Nakama, custom)
---

# Alliance (동맹)

## 매 한 줄
> **"매 player-formed group — shared goals, shared resources, shared identity"**. 매 MMO/SLG 의 retention 핵심 system. 매 EverQuest guild (1999) → World of Warcraft guild (2004) → Lords Mobile/Rise of Kingdoms 동맹 (2017+). 매 2026 modern SLG (4X/RTS hybrid) 의 core loop driver — solo player retention < 7 days, alliance member retention > 90 days 의 typical metric.

## 매 핵심

### 매 구조
- **Membership tier**: Leader / Officers (R4/R5) / Members / Recruits.
- **State**: roster, treasury, buff inventory, war declarations, territory.
- **Permissions**: hierarchical RBAC — invite/kick/promote/demote/disband.
- **Lifecycle**: create → recruit → grow → war → decline → disband.

### 매 server-authoritative invariants
- 매 single alliance per player 의 enforcement (atomic).
- Member cap (typical 50–100) — atomic check-and-insert.
- Treasury balance — race-free debit/credit (transactional).
- War state machine — pending/active/peace transitions.

### 매 응용
1. **SLG 4X game** (Lords Mobile pattern) — alliance buffs, rallies, KvK.
2. **MMO guild** (WoW pattern) — guild bank, calendar, perk levels.
3. **Mobile RPG clan** (Clash of Clans pattern) — clan wars, donations.
4. **Social fitness app** (Strava clubs) — challenges, leaderboards.

## 💻 패턴

### Schema (Postgres)
```sql
CREATE TABLE alliances (
  id BIGSERIAL PRIMARY KEY,
  tag VARCHAR(5) UNIQUE NOT NULL,
  name VARCHAR(40) NOT NULL,
  leader_id BIGINT NOT NULL REFERENCES players(id),
  member_cap SMALLINT NOT NULL DEFAULT 50,
  treasury_gold BIGINT NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE alliance_members (
  player_id BIGINT PRIMARY KEY REFERENCES players(id),
  alliance_id BIGINT NOT NULL REFERENCES alliances(id) ON DELETE CASCADE,
  rank SMALLINT NOT NULL,  -- 1=member..5=leader
  joined_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON alliance_members (alliance_id);
```

### Atomic join (server)
```typescript
async function joinAlliance(playerId: bigint, allianceId: bigint) {
  return await db.tx(async (t) => {
    // 1. Player must not be in any alliance
    const existing = await t.oneOrNone(
      "SELECT 1 FROM alliance_members WHERE player_id=$1 FOR UPDATE", [playerId]);
    if (existing) throw new Error("ALREADY_IN_ALLIANCE");

    // 2. Member cap check (lock alliance row)
    const a = await t.one(
      "SELECT member_cap, (SELECT COUNT(*) FROM alliance_members WHERE alliance_id=$1)::int AS n " +
      "FROM alliances WHERE id=$1 FOR UPDATE", [allianceId]);
    if (a.n >= a.member_cap) throw new Error("ALLIANCE_FULL");

    await t.none(
      "INSERT INTO alliance_members(player_id, alliance_id, rank) VALUES($1,$2,1)",
      [playerId, allianceId]);
  });
}
```

### Permission check
```typescript
const PERMS = {
  invite: 2,    // R2+
  kick:   3,    // R3+
  promote:4,    // R4+
  disband:5,    // leader only
} as const;

function can(memberRank: number, action: keyof typeof PERMS): boolean {
  return memberRank >= PERMS[action];
}
```

### Alliance chat (Redis pub/sub)
```typescript
// Publish
await redis.publish(`alliance:${allianceId}:chat`,
  JSON.stringify({ from: playerId, msg, ts: Date.now() }));

// Subscribe (per connected client)
const sub = redis.duplicate();
await sub.subscribe(`alliance:${allianceId}:chat`, (raw) => {
  ws.send(raw);
});
```

### War declaration state machine
```typescript
type WarState = "PEACE" | "PENDING" | "ACTIVE" | "COOLDOWN";

const transitions: Record<WarState, WarState[]> = {
  PEACE:    ["PENDING"],
  PENDING:  ["ACTIVE", "PEACE"],
  ACTIVE:   ["COOLDOWN"],
  COOLDOWN: ["PEACE"],
};

function transition(from: WarState, to: WarState) {
  if (!transitions[from].includes(to))
    throw new Error(`INVALID_TRANSITION ${from}->${to}`);
}
```

### Treasury (idempotent donation)
```typescript
async function donate(playerId: bigint, amt: bigint, idemKey: string) {
  await db.tx(async (t) => {
    const dup = await t.oneOrNone(
      "SELECT 1 FROM idempotency WHERE key=$1", [idemKey]);
    if (dup) return;
    await t.none("INSERT INTO idempotency(key) VALUES($1)", [idemKey]);
    await t.none("UPDATE players SET gold = gold - $2 WHERE id=$1 AND gold >= $2", [playerId, amt]);
    await t.none("UPDATE alliances SET treasury_gold = treasury_gold + $2 WHERE id=$1", [allianceId, amt]);
  });
}
```

### Member roster cache invalidation
```typescript
async function onMembershipChange(allianceId: bigint) {
  await redis.del(`alliance:${allianceId}:roster`);
  await redis.publish(`alliance:${allianceId}:events`, JSON.stringify({type:"ROSTER_CHANGED"}));
}
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| Casual mobile, < 30 members | Single-shard SQL, simple roster |
| MMO, 100+ members, real-time chat | Sharded SQL + Redis pub/sub |
| Cross-server alliance war (KvK) | Event-sourced log + global service |
| Persistent territory control | Server-authoritative grid + alliance ownership |

**기본값**: 매 Postgres alliance/member tables + Redis pub/sub for chat/presence + idempotent treasury operations.

## 🔗 Graph
- 변형: [[Guild]] · [[Clan]] · [[Faction]]
- Adjacent: [[Leaderboard]]

## 🤖 LLM 활용
**언제**: 매 long-session retention 의 game (MMO, SLG, persistent world), 매 social cooperation 의 core mechanic.
**언제 X**: 매 short-session arcade, 매 strict-PvP only without cooperation, 매 < 1k DAU 의 single-player feel.

## ❌ 안티패턴
- **Client-authoritative membership**: 매 cheat 의 trivial (forge join). 매 server-authoritative 만.
- **No member cap**: 매 mega-alliance dominance — 매 game balance 의 destruction.
- **Synchronous broadcast**: 매 large alliance (500+) 의 chat fan-out blocks. 매 async pub/sub 의 사용.
- **Disband without grace period**: 매 leader 의 grief vector. 매 24h cooldown.

## 🧪 검증 / 중복
- Verified (Lords Mobile design, EVE Online corporation system, WoW guild system, Clash of Clans clan system).
- 신뢰도 A.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — full content (game alliance system architecture) |
