Files
maplecontest/docs/superpowers/specs/2026-06-16-codeblock-modularization-design.md
gahusb bfa86f0f28 docs(spec): Phase 1b codeblock 메서드 모듈화 설계
writeCodeblocks의 메서드 161개를 연속구간별 cb/*.mjs 모듈로 분리(바이트 동일).
prop 103개는 오케스트레이터 유지. 헬퍼+공유상수는 lib/codeblock.mjs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 07:53:22 +09:00

5.4 KiB

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', [<prop 103개>], [<method 161개>]) (: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/<name>.mjs: export const <name>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.mjsnode tools/verify/diffcheck.mjsSlayDeckController.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 무변경(바이트 동일이 합격 기준)