docs: revise game enhancement spec after review

Fix critical issues from spec review:
- Correct model.go line count (712, not 19K) and adjust Phase 1-1 scope
- Acknowledge existing chat/freeze implementations, rescope accordingly
- Add data model definitions (structs, BoltDB schemas) for all new entities
- Move logging and config externalization to Phase 1 (foundation)
- Align floor themes with boss patterns
- Add testing strategy, data migration plan, and admin API contract

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 12:02:48 +09:00
parent 07587b103e
commit dfdc18a444

View File

@@ -13,164 +13,341 @@ Catacombs 멀티플레이 로그라이크 던전 크롤러의 종합 고도화
- 4 클래스(Warrior/Mage/Healer/Rogue), 8 몬스터 + 4 보스, 20층 던전 - 4 클래스(Warrior/Mage/Healer/Rogue), 8 몬스터 + 4 보스, 20층 던전
- 턴제 전투(5초 타임아웃), 상점, 업적 10개, 리더보드 - 턴제 전투(5초 타임아웃), 상점, 업적 10개, 리더보드
- BoltDB 영속화, SSH 핑거프린트 재접속 - BoltDB 영속화, SSH 핑거프린트 재접속
- `ui/model.go` ~19K 라인 (모든 화면 로직 집중) - 인게임 채팅 구현됨 (`/` 키로 입력, `SendChat()` 브로드캐스트)
- 상태이상: 독, 화상, 빙결 이미 존재
- `ui/model.go` ~712라인 (라우팅/업데이트 디스패치), 화면별 `*_view.go`로 분리 완료
- 기존 협동 보너스: 2인 이상 같은 타겟 공격 시 +10% 대미지
## Phase 1: Foundation + Chat ## Phase 1: Foundation + Structured Logging
### 1-1. UI Refactoring ### 1-1. UI Architecture Refinement
**Problem:** `ui/model.go`가 ~19K 라인으로 모든 화면 상태를 단일 파일에서 리. 새 기능 추가 시 버그 위험 증가, 유지보수 곤란. **Problem:** `model.go` (712라인)의 `Update()` 메서드가 모든 화면의 키 입력을 하나의 switch문에서 리. 새 화면/기능 추가 시 분기가 복잡해짐.
**Design:** **Design:**
- 각 화면의 `Update`/`View` 로직을 해당 `*_view.go` 파일로 이동
- 각 화면을 독립적인 Bubble Tea `Model` 인터페이스로 추출 (`LobbyModel`, `GameModel`, `ShopModel` 등) - 각 화면을 독립적인 Bubble Tea `Model` 인터페이스로 추출 (`LobbyModel`, `GameModel`, `ShopModel` 등)
- 메인 `Model`은 화면 간 라우팅만 담당하는 컨테이너 역할 - `*_view.go`에 해당 화면의 `Update()`/`View()` 로직을 완전히 위임
- 메인 `Model`은 화면 전환 라우팅만 담당
- 공유 상태(게임 세션, DB, 뷰포트 크기 등)는 공통 `Context` 구조체로 추출 - 공유 상태(게임 세션, DB, 뷰포트 크기 등)는 공통 `Context` 구조체로 추출
**Success criteria:** `model.go` 500라인 이하의 라우터로 축소. **Success criteria:** `model.go``Update()` 메서드가 화면별 라우팅만 수행 (각 화면 로직 0라인).
### 1-2. In-game Chat ### 1-2. Chat Emote System
**Problem:** 멀티플레이에서 소통 수단이 없어 협동의 재미가 크게 떨어짐. **Note:** 기본 채팅은 이미 구현됨 (`game/session.go:SendChat`, `/` 키 입력).
**Design:** **Design:**
- `game/chat.go` — 채팅 메시지 브로드캐스트 (룸 내 플레이어 간) - 이모트 프리셋 시스템 추가 (`/hi`, `/gg`, `/go`, `/wait`, `/help`)
- 게임 화면 하단에 채팅 로그 영역 추가 - 이모트는 채팅 로그에 강조 스타일로 표시
- `/` 키로 채팅 입력 모드 전환 - `game/emote.go` — 이모트 정의 및 파싱
- 이모트 프리셋 (`/hi`, `/gg` 등)
**Affected packages:** `game/`, `ui/` ### 1-3. Structured Logging
**Rationale:** Phase 2~3 디버깅을 위해 초기에 도입.
**Design:**
- `log/slog` (Go 표준) 도입, JSON 형식 구조화 로깅
- 이벤트: 접속, 게임 시작, 전투, 종료, 에러
- 패닉 리커버리 미들웨어 — 세션 크래시 격리
### 1-4. Configuration Externalization
**Rationale:** Phase 2~3에서 밸런스 상수를 추가하기 전에 설정 구조를 먼저 도입.
**Design:**
- `config/config.go` — YAML 파싱 및 기본값 관리
- `config.yaml` — 서버 포트, 턴 타임아웃, 몬스터 스케일링, 상점 가격 배율 등
```go
type Config struct {
Server ServerConfig `yaml:"server"`
Game GameConfig `yaml:"game"`
Combat CombatConfig `yaml:"combat"`
Dungeon DungeonConfig `yaml:"dungeon"`
Backup BackupConfig `yaml:"backup"`
}
type GameConfig struct {
TurnTimeout time.Duration `yaml:"turn_timeout"` // default: 5s
MaxPlayers int `yaml:"max_players"` // default: 4
MaxFloors int `yaml:"max_floors"` // default: 20
CoopBonus float64 `yaml:"coop_bonus"` // default: 0.10
InventoryLimit int `yaml:"inventory_limit"` // default: 10
}
```
**Affected packages:** 전체 (상수 참조 부분), `server/`, `game/`
## Phase 2: Combat & Dungeon Enhancement ## Phase 2: Combat & Dungeon Enhancement
### 2-1. Combat System Expansion ### 2-1. Combat System Expansion
**Skill Tree:** **Skill Tree:**
- 클래스별 3갈래 특성 트리 (예: Warrior → 탱커/버서커/전술가) - 클래스별 2갈래 특성 트리 (MVP, 추후 3갈래 확장 가능)
- 층 클리어 시 포인트 획득, 런 내에서만 유효 (로그라이크 특성 유지) - Warrior: 탱커 / 버서커
- `entity/skill_tree.go` — 트리 정의 및 포인트 적용 로직 - Mage: 원소술사 / 시간술사
- Healer: 수호자 / 사제
- Rogue: 암살자 / 약사
- 층 클리어 시 1포인트 획득, 브랜치당 3노드, 런 내에서만 유효
- 스킬 포인트 배분은 층 이동 화면에서 수행 (턴 동기화 불필요)
```go
// entity/skill_tree.go
type SkillBranch struct {
Name string
Nodes [3]SkillNode // 3 sequential unlocks per branch
Description string
}
type SkillNode struct {
Name string
Effect SkillEffect // enum: ATKBoost, DEFBoost, SkillPower, etc.
Value float64 // modifier amount
Required int // points spent in branch to unlock
}
type PlayerSkills struct {
BranchIndex int // 0 or 1 (chosen branch)
Points int // total points earned
Allocated int // points allocated in chosen branch
}
```
**Combo Skills:** **Combo Skills:**
- 2인 이상이 같은 턴에 특정 조합 사용 시 연계 효과 발동 - 2인 이상이 같은 턴에 특정 조합 사용 시 연계 효과 발동
- 예: Mage 빙결 + Warrior 강타 = 빙쇄 대미지 - 기존 협동 보너스(+10%)와 별개로 스택됨
- `combat/combo.go` — 연계 조건 판정 및 효과 적용 - 예: Mage 빙결 + Warrior 강타 = 빙쇄 (대미지 1.5배 + 빙결 해제)
```go
// combat/combo.go
type ComboDefinition struct {
RequiredActions []ComboAction // class + action type pairs
Effect ComboEffect
Name string
Description string
}
type ComboAction struct {
Class entity.Class
ActionType string // "skill", "attack"
SkillName string // optional: specific skill required
}
```
**Elite Monsters:** **Elite Monsters:**
- 일반 몬스터의 강화 변종, 특수 접두사 (맹독의/불타는/흡혈의) - 일반 몬스터의 강화 변종, 층당 ~20% 확률로
- 보스가 아닌 층에서 긴장감 추가 - 접두사별 스탯 변형 및 특수 능력
- `entity/elite.go` — 접두사 시스템 및 스탯 변형
```go
// entity/elite.go
type ElitePrefix struct {
Name string // "맹독의", "불타는", "흡혈의"
StatMod StatModifier // HP/ATK/DEF multipliers
OnHit StatusEffect // applied on monster's attack
DropBonus float64 // extra loot chance
}
```
**Status Effects Expansion:** **Status Effects Expansion:**
- 기존: 독, 화상 - 기존: 독, 화상, 빙결
- 추가: 빙결(행동 불가), 출혈(턴마다 누적), 저주(회복량 감소) - 추가: 출혈(턴마다 대미지 누적 +1), 저주(회복량 50% 감소)
- `entity/status.go` 확장 - `entity/player.go``StatusBleed`, `StatusCurse` 추가
**Affected packages:** `entity/`, `combat/`, `game/` **Success criteria:** 8개 스킬 브랜치, 5개 이상 콤보 조합, 5개 엘리트 접두사, 5개 상태이상.
### 2-2. Dungeon Event Diversification ### 2-2. Dungeon Event Diversification
**Random Event Rooms:** **Random Event Rooms:**
- 선택지 기반 이벤트 (예: "수상한 제단 발견" → 제물 바치기/무시/파괴) - 선택지 기반 이벤트 (예: "수상한 제단 발견" → 제물 바치기/무시/파괴)
- 각 선택지마다 다른 보상/페널티 - 최소 8개 이벤트 풀
- `game/random_event.go` — 이벤트 풀 및 결과 처리
```go
// game/random_event.go
type RandomEvent struct {
ID string
Description string
Choices []EventChoice
}
type EventChoice struct {
Text string
Outcome EventOutcome // reward/penalty/mixed
Weight float64 // probability weight
}
```
**Secret Rooms:** **Secret Rooms:**
- 낮은 확률(~10%)로 생성, 희귀 아이템/렐릭 보상 - 낮은 확률(~10%)로 생성, `dungeon/room.go``RoomSecret` 타입 추가
- `dungeon/generator.go` 확장 - 희귀 아이템/렐릭 보상
**Floor Themes:** **Floor Themes:**
- 5층 단위로 환경 효과 - 5층 단위로 환경 효과, 보스 패턴과 테마 정렬:
- 1~5층 습지: 독 대미지 증가 - 1~5층 습지 (독 강화) → Guardian 보스 (독 패턴으로 변경)
- 6~10층 화산: 화상 대미지 증가 - 6~10층 화산 (화상 강화) → Warden 보스 (화상 패턴으로 변경)
- 11~15층 얼음: 빙결 확률 증가 - 11~15층 얼음 (빙결 강화) → Overlord 보스 (빙결 패턴)
- 16~20층 지옥: 모든 상태이상 강화 - 16~20층 지옥 (전체 강화) → Archfiend 최종 보스
- `dungeon/theme.go` — 테마별 환경 효과 정의
```go
// dungeon/theme.go
type FloorTheme struct {
Name string
StatusBoost entity.StatusEffect // which status is empowered
DamageModifier float64 // multiplier for boosted status
AsciiStyle string // visual theme for rendering
}
```
**Mini-boss Rooms:** **Mini-boss Rooms:**
- 보스 층 직전(4, 9, 14, 19층)에 미니보스 등장 - 보스 층 직전(4, 9, 14, 19층)에 미니보스 등장
- 보스 전 준비 테스트 역할 - 기존 `Monster` 구조체에 `IsMiniBoss bool` 추가, `BossPattern` 사용하되 HP/ATK는 보스의 60%
**Affected packages:** `dungeon/`, `game/`, `entity/` **Prerequisite for Phase 3-1:** 던전 생성을 시드 기반으로 리팩토링.
- `GenerateFloor(floor int)``GenerateFloor(floor int, rng *rand.Rand)`
- 모든 랜덤 호출을 `rng` 인스턴스로 교체
**Success criteria:** 8개 이상 랜덤 이벤트, 4개 층 테마, 비밀 방, 4개 미니보스.
**Affected packages:** `dungeon/`, `game/`, `entity/`, `combat/`
## Phase 3: Retention Systems ## Phase 3: Retention Systems
### 3-1. Daily Challenge ### 3-1. Daily Challenge
- 날짜 기반 시드로 동일 던전 구조/몬스터 배치 생성 - 날짜 기반 시드(`time.Now().Format("2006-01-02")` → hash → seed)로 동일 던전 생성
- Phase 2-2에서 리팩토링된 시드 기반 생성기 활용
- 일일 전용 리더보드 - 일일 전용 리더보드
- 참여 시 포인트 적립, 연속 참여 보너스
- `game/daily.go` — 시드 생성 및 일일 세션 관리 ```go
- `store/daily.go` — 일일 기록 및 연속 참여 추적 // store/daily.go (BoltDB bucket: "daily_runs")
// Key: "YYYY-MM-DD:playerFingerprint"
type DailyRecord struct {
Date string `json:"date"`
Player string `json:"player"`
FloorReached int `json:"floor_reached"`
GoldEarned int `json:"gold_earned"`
Streak int `json:"streak"` // consecutive days played
}
```
**Success criteria:** 동일 날짜에 같은 시드 던전 보장, 일일 리더보드 표시.
### 3-2. Meta Progression ### 3-2. Meta Progression
**Unlock System Expansion:** **Unlock System:**
- 현재 업적 10개 → 조건부 언락 콘텐츠 추가
- "10층 이상 클리어" → 5번째 클래스 해금 ```go
- "3인 이상 클리어" → 하드 모드 해금 // store/unlocks.go (BoltDB bucket: "unlocks")
- `store/unlocks.go` — 언락 조건 및 상태 관리 // Key: "playerFingerprint:unlockID"
type Unlock struct {
ID string `json:"id"`
Condition string `json:"condition"` // human-readable
Unlocked bool `json:"unlocked"`
}
```
언락 콘텐츠:
- "10층 이상 클리어" → 5번째 클래스 해금
- "3인 이상 클리어" → 하드 모드 해금
- "20층 클리어" → 주간 변이 모드 해금
**Player Titles:** **Player Titles:**
- 업적/기록 기반 칭호 부여
- 로비에서 닉네임 옆에 표시 ```go
- `store/titles.go` — 칭호 정의 및 부여 로직 // store/titles.go (BoltDB bucket: "titles")
// Key: "playerFingerprint"
type PlayerTitle struct {
ActiveTitle string `json:"active_title"`
Earned []string `json:"earned"` // list of title IDs
}
```
**Codex System:** **Codex System:**
- 조우한 몬스터/획득한 아이템/발견한 이벤트 기록
- 도감 완성률 표시 ```go
- `store/codex.go` — 도감 데이터 관리 // store/codex.go (BoltDB bucket: "codex")
- `ui/codex_view.go` — 도감 화면 // Key: "playerFingerprint"
type Codex struct {
Monsters map[string]bool `json:"monsters"` // monsterID → encountered
Items map[string]bool `json:"items"` // itemID → acquired
Events map[string]bool `json:"events"` // eventID → discovered
}
```
- `ui/codex_view.go` — 도감 화면, 완성률 표시
**Success criteria:** 3개 이상 언락 콘텐츠, 5개 이상 칭호, 도감 완성률 추적.
### 3-3. Difficulty System ### 3-3. Difficulty System
**Hard Mode:** **Hard Mode:**
- 난이도 배율은 `config.yaml`에서 관리 (Phase 1-4의 설정 구조 활용)
- 몬스터 스탯 1.5배, 상점 가격 2배, 회복량 절반 - 몬스터 스탯 1.5배, 상점 가격 2배, 회복량 절반
- 언락 조건 충족 시 선택 가능 - 언락 조건 충족 시 로비에서 선택 가능
**Weekly Mutations:** **Weekly Mutations:**
- 매주 바뀌는 특수 규칙 - 매주 바뀌는 특수 규칙, 주 번호 기반 시드로 결정
- "스킬 사용 불가", "엘리트만 등장", "상점 없음" 등
- `game/mutation.go` — 주간 변이 규칙 정의 및 적용
**Affected packages:** `game/`, `store/`, `ui/` ```go
// game/mutation.go
type Mutation struct {
ID string
Name string // "스킬 봉인", "엘리트 범람", "상점 폐쇄" 등
Description string
Apply func(cfg *config.GameConfig) // config 값 오버라이드
}
```
**Affected packages:** `game/`, `store/`, `ui/`, `config/`
## Phase 4: Operational Stability ## Phase 4: Operational Stability
### 4-1. Logging & Monitoring ### 4-1. Admin Dashboard
- `log/slog` (Go 표준) 도입, JSON 형식 구조화 로깅 - `/admin` HTTP 엔드포인트 (Basic Auth 인증)
- 이벤트: 접속, 게임 시작, 전투, 종료, 에러 - JSON 응답 형식:
- `/admin` HTTP 엔드포인트 — 접속자 수, 활성 방, 오늘의 런 수, 평균 클리어 층수
- 패닉 리커버리 미들웨어 — 세션 크래시 격리
**Affected packages:** `server/`, `web/`, `game/` ```go
type AdminStats struct {
OnlinePlayers int `json:"online_players"`
ActiveRooms int `json:"active_rooms"`
TodayRuns int `json:"today_runs"`
AvgFloorReach float64 `json:"avg_floor_reached"`
Uptime time.Duration `json:"uptime"`
}
```
### 4-2. Data Safety ### 4-2. Data Safety
- 설정 가능한 주기로 DB 파일 자동 백업 (`./data/backup/`) - 설정 가능한 주기로 DB 파일 자동 백업 (`./data/backup/`, `config.yaml``backup.interval`)
- 그레이스풀 셧다운: SIGTERM 시 진행 중인 세션 저장 후 종료 - 그레이스풀 셧다운: SIGTERM 시 진행 중인 세션 저장 후 종료
- 재시작 시 미완료 세션 정리 - 재시작 시 미완료 세션 정리
**Affected packages:** `store/`, `main.go` **Affected packages:** `store/`, `web/`, `main.go`
### 4-3. Configuration Externalization ## Data Migration
- `config.yaml` — 서버 포트, 턴 타임아웃, 몬스터 스케일링, 상점 가격 배율 등 기존 BoltDB 데이터와의 호환성:
- 밸런스 조정 시 재빌드 없이 설정 파일만 수정 - 새 버킷(`daily_runs`, `unlocks`, `titles`, `codex`)은 `CreateBucketIfNotExists`로 안전하게 추가
- `config/config.go` — YAML 파싱 및 기본값 관리 - 기존 `profiles`, `rankings`, `achievements` 버킷은 구조 변경 없음
- 업적 시스템과 언락 시스템은 별도 버킷으로 독립 운영 (기존 업적 데이터 보존)
**Affected packages:** 전체 (상수 참조 부분) ## Testing Strategy
- **단위 테스트:** 새 패키지별 `*_test.go` (스킬 트리 포인트 계산, 콤보 판정, 엘리트 스탯 변형)
- **시드 결정성 테스트:** 동일 시드 → 동일 던전 보장 검증
- **밸런스 시뮬레이션:** 엘리트/미니보스 스탯 범위가 솔로/파티 모두에서 적정한지 수치 검증
- **통합 테스트:** 턴 실행 시 콤보 판정 → 대미지 계산 → 상태이상 적용 흐름
## Dependencies Between Phases ## Dependencies Between Phases
``` ```
Phase 1 (Foundation) Phase 1 (Foundation: UI정리 + 로깅 + 설정 외부화)
── Phase 2 (Combat/Dungeon) — UI 리팩토링 완료 후 새 화면 추가가 용이 ── Phase 2 (Combat/Dungeon) — 설정 구조 위에 밸런스 상수 추가
└── Phase 3 (Retention) — 전투/던전 콘텐츠 위에 메타 시스템 구축 └── Phase 3 (Retention) — 시드 기반 생성기, 콘텐츠 위에 메타 시스템
└── Phase 4 (Operations) — 전체 기능 완성 후 운영 도구 보강 └── Phase 4 (Operations) — 로깅 기반 위에 어드민/백업 추가
``` ```
Phase 4의 로깅/설정 외부화는 독립적이므로, 필요 시 Phase 2~3과 병행 가능. Phase 4는 Phase 1 완료 후 독립 진행 가능 (Phase 2~3과 병행).
## Out of Scope ## Out of Scope