gen-slaydeck.mjs UI emit 16종을 lib/+hud/ 모듈로 분리(출력 바이트 동일·무위험). codeblock 메서드 제외. 하이브리드 단계적: Phase2 캐릭터선택 메이커 저작 파일럿. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.1 KiB
7.1 KiB
생성기 모듈화 (Phase 1) + 하이브리드 UI 로드맵 설계
작성일: 2026-06-16
브랜치: feature/gen-modularization
배경 / 동기
DefaultGroup.ui에 모든 UI(캐릭터 선택·상점·전체 덱·전투…)가 들어 있어, 사용자가 (a) 생성기 코드 유지보수와 (b) 메이커에서 기능별 시각 편집을 원함.
핵심 제약(브레인스토밍에서 확정): MSW에서 "Layer"는 렌더 z순서일 뿐 논리 분리 도구가 아니고, 실제 UI 그룹 단위는 UIGroup(.ui 파일 = UIGroup, 현재 Default/Popup/Toast 3개). 그리고 같은 UI를 '생성'과 '메이커 수동 편집' 둘 다로 둘 수 없음(재생성이 수동 편집을 덮어씀).
→ 소유 모델 = 하이브리드·단계적(사용자 승인): 정적 레이아웃은 메이커 저작(시각 편집), 동적 내용은 컨트롤러가 런타임 주입. 단, 한 번에 안 하고 단계적으로.
로드맵 (단계적 — 각 Phase가 자체 spec→plan)
- Phase 1 (이 문서):
gen-slaydeck.mjs(~6,200줄)의 UI emit을 기능별 모듈로 분리. 출력.ui/codeblock바이트 동일(순수 리팩터·무위험). (a) 충족 + (b) 토대(화면별 파일). - Phase 2 (후속 spec): 화면 1개(캐릭터 선택) 파일럿 — 정적 레이아웃을 메이커 저작 UIGroup으로 이관, 생성기는 그 화면 emit 중단,
SlayDeckController가 경로로 내용(이미지·텍스트) 주입. (b) 패턴 검증. - Phase 3 (후속 spec): 검증되면 상점·전체덱 등으로 확장.
현재 구조 (조사 결과)
- 공유 인프라(~48–530):
luaSoulShopTable/luaFramesTable/luaNodeIconsTable/luaRelicsTable/luaPotionsTable/luaIntentsArray/luaEnemiesTable/luaStr/luaJobsTable/luaCardsTable/luaDeckTable/frameRuid/cardFaceLayout/guid/transform/sprite/button/text/scrollLayoutGroup/entity/uiPath/sectionRoot/isGeneratedUiEntity/appendUiSection. 데이터 로드 상수(CARDS/CHARS/ENEMIES/RELICS/POTIONS/CARDFRAMES/NODEICONS/CAM) 및 색·치수 상수(GOLD/WHITE/TRANSPARENT/ALIGN_*/CARD_W/CARD_H 등). guid(prefix, n)은 순수 함수(:284, 내부 카운터 없음; ns는 prefix→바이트 매핑). 모듈 호출 순서와 무관하게 동일 guid → 분리해도 바이트 동일.upsertUi()(:529)가 UI 오케스트레이터: 기존DefaultGroup.ui로드 → 생성 섹션 필터(stock 보존) → 로컬emit(section, entities)클로저로 누적 → CardHand 스톡카드 in-place upsert(:565–691, 특수) → HUD별const x=[]; const add=…; add(entity(...)); …; emit('X', x)→ (말미) 병합·기록.- HUD emit 16종(순서·라인): DeckHud(
:808) · DeckInspectHud(:942) · DeckAllHud(:1097) · CombatHud(:1587) · RewardHud(:1681) · MapHud(:1839) · ShopHud(:2038) · RestHud(:2095) · TreasureHud(:2181) · JobChoiceHud(:2229) · JobSelectHud(:2314) · MainMenu(:2616) · CharacterSelectHud(:2617) · LobbyHud(:2672) · BoardHud(:2727) · SoulShopHud(:2814). 각 섹션은 서로의 지역변수 비참조(헬퍼·데이터 상수만 사용). - codeblock 메서드(
prop/method/codeblock/writeCodeblocks:2836–6124, ~3,200줄) + patchCommon(:6125). Phase 1 범위 제외.
Phase 1 상세 설계
목표 파일 구조
tools/deck/
gen-slaydeck.mjs # 오케스트레이터(축소): import lib+hud → 데이터 로드 → upsertUi(HUD 모듈 순차) → writeCodeblocks → patchCommon
lib/
ui-helpers.mjs # guid, transform, sprite, button, text, entity, scrollLayoutGroup,
# 상수(GOLD/WHITE/TRANSPARENT/ALIGN_*/CARD_W/CARD_H/UI_ROOT 등), cardFaceLayout,
# uiPath/sectionRoot/isGeneratedUiEntity/appendUiSection
data.mjs # CARDS/CHARS/ENEMIES/RELICS/POTIONS/CARDFRAMES/NODEICONS/CAM 로드·검증
# + luaXxxTable·frameRuid
hud/
deckhud.mjs deckinspect.mjs deckall.mjs combat.mjs reward.mjs map.mjs
shop.mjs rest.mjs treasure.mjs jobchoice.mjs jobselect.mjs mainmenu.mjs
charselect.mjs lobby.mjs board.mjs soulshop.mjs
모듈 계약
- 각
hud/<name>.mjs:export function build<Name>()→ 자기 HUD 엔티티 배열 반환. 필요한 헬퍼·상수·데이터는lib/에서 import(거대 deps 객체 전달 금지). upsertUi()(오케스트레이터에 잔류)는 기존 순서 그대로emit('DeckHud', buildDeckHud())…emit('SoulShopHud', buildSoulShop())호출.emit·섹션 병합 로직 불변.- CardHand 스톡카드 in-place upsert(
:565–691)는 기존.ui엔티티를 변형하는 특수 로직 → 오케스트레이터(또는hud/cardhand.mjs)에 그대로 유지. import 경계만 정리.
바이트 동일 불변식 (가장 중요)
- 리팩터는 출력 변경 0이 목표. 보장 근거: guid 순수·emit 순서·entity 구성 모두 보존, 로직 이동만.
- 합격 기준: 리팩터 후
node tools/deck/gen-slaydeck.mjs→git diff결과가ui/DefaultGroup.ui·SlayDeckController.codeblock에 0 변경(Global/common.gamelogic은 LF churn만 허용 →git checkout).
증분 실행 전략
- 한 번에 16개 다 옮기지 말고 HUD 1~2개씩 추출 → 재생성 →
git diff빈 결과 확인 → 커밋 반복. 첫 추출(예: SoulShopHud 같은 말단 + lib 골격) 성공 후 패턴 반복. - lib 추출(헬퍼·상수·데이터) 먼저 → 그 다음 HUD 모듈을 하나씩 lib import로 전환.
미러/테스트·하네스
- 전투규칙·맵생성 Lua 무변경 →
sim-balance/rogue-map미러 동기화 불필요(회귀 확인차node --test실행). - RULES 동기화: 생성기가 다중 파일이 되므로 RULES §1 "단일 소스"/보조 생성기 표를
tools/deck/(gen-slaydeck + lib/ + hud/)로 갱신.
범위 밖 (명시)
- codeblock 메서드(
method()~3,200줄) 분리 — 더 크고 (b)와 무관·리스크↑. 원하면 별도 Phase 1b spec. - 게임 동작·데이터·런타임 로직 변경. (순수 소스 리팩터)
- UIGroup 분할·메이커 저작 이관 — Phase 2 이후.
리스크
- 클로저 참조(헬퍼/상수)를 import로 전환하는 광범위·기계적 수정 — 누락 시 런타임 throw 또는 출력 diff로 즉시 노출(바이트 검증이 안전망).
- 상수 정의 위치 산재(CARD_W·GOLD·UI_ROOT 등 top-level) — lib로 이동 시 누락 주의. 추출 전
grep으로 전체 상수 인벤토리 작성. - ESM 순환 import 주의(lib는 hud를 import하지 않음 — 단방향: orchestrator→hud→lib).
변경 파일 요약
| 파일 | 변경 |
|---|---|
tools/deck/lib/ui-helpers.mjs, lib/data.mjs |
신설 — 공유 헬퍼·상수·데이터 |
tools/deck/hud/*.mjs (16) |
신설 — HUD별 build 함수 |
tools/deck/gen-slaydeck.mjs |
오케스트레이터로 축소(데이터/UI emit 본문 → 모듈로 이동, import·호출만) |
RULES.md |
§1 보조 생성기/단일소스 표에 lib/·hud/ 반영 |
ui/DefaultGroup.ui·SlayDeckController.codeblock |
무변경(바이트 동일이 합격 기준) |