diff --git a/docs/superpowers/specs/2026-06-16-codeblock-modularization-design.md b/docs/superpowers/specs/2026-06-16-codeblock-modularization-design.md new file mode 100644 index 0000000..fac0a1d --- /dev/null +++ b/docs/superpowers/specs/2026-06-16-codeblock-modularization-design.md @@ -0,0 +1,69 @@ +# Phase 1b — codeblock 메서드 모듈화 설계 + +작성일: 2026-06-16 +브랜치: `feature/cb-modularization` (Phase 1 `feature/gen-modularization`/PR #70 위에 스택) + +## 목표 + +Phase 1에서 UI emit을 모듈화한 데 이어, `gen-slaydeck.mjs`의 **codeblock 메서드 161개(~3,200줄)**를 기능별 모듈로 분리한다. 출력 `RootDesk/MyDesk/SlayDeckController.codeblock`은 **바이트 동일**(순수 소스 리팩터·무위험). 하이브리드 UI 로드맵 (a) 유지보수 정리의 완결. + +## 현재 구조 (조사 결과) + +- `writeCodeblocks()`(현 `gen-slaydeck.mjs:291`)가 단일 호출로 codeblock을 만든다: + `const combat = codeblock('SlayDeckController', 'SlayDeckController', [], [])` (`:301`~`:3617`, ~3,300줄). +- 헬퍼: `prop()`·`method()`·`codeblock()` (현 `:240`~`:290` 부근, 오케스트레이터 잔류분). +- `writeCodeblocks` 지역 상수: `RUN_LENGTH`·`GOLD_PER_WIN`·`CARD_PRICE`·`REST_HEAL`·`RELIC_PRICE`·`ACT_COUNT`·`ACT_MAPS`·`LOBBY_MAP`·`LOBBY_SPAWN` 등 — 메서드 Lua 문자열 보간에 쓰임. +- 메서드 본문은 **Lua 문자열**. JS 보간(`${RUN_LENGTH}`·`${luaCardsTable(CARDS.cards)}`·`${CAM.zoomRatio}` 등)은 모듈 로드 시점에 평가됨 → 모듈은 보간에 쓰는 상수/데이터/헬퍼를 import해야 한다. +- 161 메서드 이름(순서): OnBeginPlay → [ascension 10종] → HideGameHud·ShowState·ShowMainMenu·BindMenuButtons·ShowLobby… → [soul 12종] → [character/job] → StartRun·StartCombat·[combat 다수] → [deck/hand] → [deckview] → [motion] → [relics/potions] → [tooltip] → [reward] → [map] → [shop/rest/treasure]. 자연스러운 **연속 런(run)**으로 묶임. + +## 상세 설계 + +### 핵심 제약: 바이트 동일 → 메서드 순서 보존 +`codeblock`의 methods 배열은 **순서가 직렬화에 반영**된다. 따라서 모듈은 "기능 버킷"이 아니라 **원본 161-메서드 시퀀스의 연속 구간**으로 나눈다(구간을 그 테마로 명명). `writeCodeblocks`가 모듈 배열을 **원본 순서대로 concat** → 바이트 동일. (Phase 1 HUD 분리와 동일 원리: HUD도 upsertUi 내 연속이었음.) + +### 목표 파일 구조 +``` +tools/deck/ + gen-slaydeck.mjs # 오케스트레이터: writeCodeblocks()가 codeblock(…, [props], [...m1, ...m2, …]) concat + lib/ + codeblock.mjs # 신설 — prop()·method()·codeblock() 헬퍼 + writeCodeblocks 지역 상수 + # (RUN_LENGTH·GOLD_PER_WIN·CARD_PRICE·REST_HEAL·RELIC_PRICE·ACT_COUNT·ACT_MAPS·LOBBY_MAP·LOBBY_SPAWN …) + cb/ # 신설 — 메서드 연속구간 모듈 (각 `export const xMethods = [ method(...), … ]`) + state.mjs ascension.mjs soul.mjs jobs.mjs run.mjs combat.mjs + deck.mjs deckview.mjs motion.mjs items.mjs tooltip.mjs reward.mjs shop.mjs … (~12-14, 실제 런 경계로 확정) +``` + +### 모듈 계약 +- 각 `cb/.mjs`: `export const Methods = [ method('A', \`…\`, …), method('B', …), … ];` — **메서드 호출 verbatim 이동**. +- import: `lib/codeblock.mjs`(method·prop·codeblock·상수), `lib/data.mjs`(CARDS·luaCardsTable·luaStr·CAM 등 보간용). UI 헬퍼는 메서드 보간에 거의 안 쓰임(필요 구간만 `lib/ui-helpers.mjs`). +- `writeCodeblocks()`(오케스트레이터): `codeblock('SlayDeckController','SlayDeckController', [ ...props ], [ ...stateMethods, ...ascensionMethods, … ])` — concat 순서 = 원본 순서. + +### 범위/결정 +- **메서드 161개만 모듈화.** **prop 103개는 오케스트레이터에 단일 리스트로 유지** — 한 줄짜리라 분리 가치 낮고 prop↔feature 매핑 모호(추후 필요시 별도). 게임 로직·Lua **무변경**(순수 소스 리팩터). +- 공유 헬퍼(method/prop/codeblock) + writeCodeblocks 지역 상수 → `lib/codeblock.mjs`. (이 상수들이 메서드 모듈 보간에 필요하므로 lib로.) + +### 검증 (안전망) +- 구간 추출마다 `node tools/deck/gen-slaydeck.mjs` → `node tools/verify/diffcheck.mjs` → `SlayDeckController.codeblock` **IDENTICAL**(`ui`·`common` 무영향이나 함께 확인). 증분(구간 1~2개씩) + 커밋. +- 미러 테스트 `sim-balance`·`rogue-map` 무영향(회귀 확인차 실행). +- 전투규칙·맵생성 Lua 미변경 → 미러 동기화 불필요. + +### 미러/하네스 +- RULES §1의 gen-slaydeck 단일소스에 `cb/`·`lib/codeblock.mjs` 추가 반영. + +## 범위 밖 +- prop 모듈화(추후). +- Phase 2(메이커 UIGroup 파일럿). +- 게임 동작·데이터 변경. + +## 리스크 +- 메서드가 writeCodeblocks **지역변수/다른 메서드 정의를 JS레벨로 참조**하면(드묾 — 대부분 Lua 문자열 내 `self:Method()` 런타임 호출이라 JS-무관) 추출 시 undefined → diffcheck/throw로 즉시 노출 → 그 구간만 인자/상수 조정. +- 모듈 import는 ui-helpers처럼 export 이름 자동 파생로 누락 방지. 단방향 의존 orchestrator→cb→lib(순환 없음). + +## 변경 파일 요약 +| 파일 | 변경 | +|---|---| +| `tools/deck/lib/codeblock.mjs` | **신설** — prop/method/codeblock 헬퍼 + 공유 상수 | +| `tools/deck/cb/*.mjs` (~12-14) | **신설** — 메서드 연속구간 모듈 | +| `tools/deck/gen-slaydeck.mjs` | writeCodeblocks를 import+concat로 축소(메서드 본문 → 모듈) | +| `RULES.md` | §1에 cb/·lib/codeblock 반영 | +| `SlayDeckController.codeblock`·`ui`·`common` | **무변경**(바이트 동일이 합격 기준) |