CLAUDE.md had grown to 3196 lines of accumulated session logs, causing context bloat. Full session narratives (including trial-and-error and later-corrected reasoning — quadnomicon devlog raw material) now live as 39 individual files under .claude/session/. CLAUDE.md keeps only a short "지금 할 일" (re-synced against question.md/pre-implementation-audit.md, stale detail dropped) and a compact per-session summary+link table. No design decisions changed; base/research/question.md were already in sync with every session (verified against README.md/question.md before archiving), so no unreflected content needed migrating first.
7.3 KiB
2026-08-08 두 번째 세션 — Dispatch는 프리미티브가 아니라 탑레벨 싱글톤 확정,
네이밍 케이싱 컨벤션 신설, Handler를 세 번째 카테고리로 명문화
같은 날 이어진 세션. 사용자가 위 4번 미결 항목("Ref/Observer/PreRef leaf
Handler가 어디 사는지")을 다시 짚으며 시작 — "Handler도 실제 런타임 값이
생기는 요소인데 왜 프리미티브로 안 다루나", "Dispatch는 어떻게 되는 거냐,
State 핸들러 안에서 getHandler를 부르려면 Dispatch가 이미 존재해야
하는데" 하는 질문으로 확장돼 Dispatch 자체의 정체성(싱글톤 top-level
함수 모음 vs 인스턴스화 가능한 프리미티브) 논의로 이어짐. 네 가지로 정리,
전부 base/bind-system-plan.md/base/store-semantics.md/
base/architecture.md/question.md/ROADMAP.md에 반영 완료:
1. Dispatch는 프리미티브가 아니라 탑레벨 싱글톤 — 확정, 지금 형태 유지.
Dispatch.process/getHandler/addHandler/drive를 Source/Ref처럼
생성자 있는 프리미티브로 바꿀지 검토했으나 기각. 근거: (a) Tween/
NoneHandler/StoreBind가 자기 process 안에서 다시 Dispatch.process를
재귀 호출해야 해서, canExecute/bindLifetime처럼 require 한 번으로 바로
닿는 안정된 전역이어야 함 — 프리미티브화하면 모든 Handler 호출 경로에
Dispatch 핸들을 실어날라야 하는 스레딩 비용이 생기는데 지금은 그 비용이
없음. (b) 사용자가 우려한 "Handler가 Dispatch 원하고 Dispatch가 Handler
원해서 순환참조" 문제는 착시로 확인됨 — "Handler"가 (i) Handler.luau의
순수 타입 계약(leaf, Dispatch를 몰라도 됨)과 (ii) 그 계약을 구현하는
concrete 값 모듈(StoreBind.luau류, 재귀호출 위해 Dispatch를 참조)
두 가지를 가리켜서 헷갈렸던 것 — 의존 방향은 Handler.luau ←
Dispatch/init.luau ← StoreBind.luau로 항상 한쪽으로만 흐름, 사이클
없음. (c) 모듈 재생성(New())과의 관계도 새 설계가 필요 없음 — 이미
확정된 "팩토리가 BaseModule을 뮤테이션" 패턴을 그대로 따르면
_initializedBy 마커에 대해 이미 나왔던 결론("New()가 생기면 각
인스턴스가 별도 테이블이 되므로 자연히 스코핑됨")이 Dispatch의 handler
레지스트리에도 그대로 적용됨. v1처럼 require를 감싸는 Init(QuadId?)
방식은 채택 안 함(id 기반 조회 자체가 Ref로 대체되며 이미 기각된 패턴).
base/bind-system-plan.md의 "Dispatch는 프리미티브가 아니다" 절,
base/architecture.md 13번 항목에 반영.
2. quad-base 기본 핸들러도 전부 같은 Dispatch.addHandler 레지스트리를
공유 — Ref/Observer/PreRef leaf Handler 위치 확정. NoneHandler/
Dispatch/StoreBind.luau뿐 아니라, children 배열 숫자 슬롯에 Ref/
Observer/PreRef를 직접 놓는 leaf 값을 매칭하는 Handler도 같은 부류 —
inst를 any로 취급하고 엔진 특정 API가 필요 없으니 quad-base,
Dispatch/Leaf.luau로 확정(위 4번 미결 항목 해소). quad-roblox의
Property/Event/Tween 핸들러도 같은 레지스트리에 등록되므로, base
기본 핸들러와 backend 핸들러가 별도 경로로 안 갈리고 하나의 우선순위
스캔을 공유한다는 것도 명시적으로 확인됨. architecture.md 소스트리에
Dispatch/Leaf.luau 반영, question.md/ROADMAP.md M2 동기화.
3. Handler는 "독립 프리미티브 vs 파생 데이터" 분류의 세 번째, 별개
카테고리 — 명문화. 2026-08-06 후속 세션이 확정한 분류(Source/Ref/Store/
Modifier=독립 프리미티브, State/Observer=파생 데이터)에 Handler가 왜
안 끼는지 사용자가 재확인 요청 — 이유: Handler는 그 자체로 구현체가
없는 순수 타입 계약이라 quad 사용자가 다루는 리액티브 값이 아님,
계약을 만족하는 값(PropertyHandler류)은 항상 구현하는 쪽(base
자신의 기본 핸들러 또는 quad-roblox 백엔드)이 채워 넣는 것이지 Type(args)
자유 함수로 사용자가 만드는 게 아니고, State/Observer처럼 어떤 원천에
종속된 파생물도 아님. base/store-semantics.md의 "일반 원칙" 절 뒤에
"세 번째 카테고리 — Handler" 절로 반영.
4. 네이밍 케이싱 컨벤션 신설 — 지금까지 나온 모든 이름이 이미 따르고
있던 규칙을 문서화만 함, 리네임 없음. 사용자 관찰: "탑레벨 함수는
변수처럼 소문자 시작, 프리미티브 타입의 메서드는 대문자 시작(파스칼
케이싱)이 맞아 보인다"는 규칙 제안 — 검증 결과 기존 이름 전체(생성자
Source/Ref/Store/Modifier/Relate/Effect, 콜론 메서드
:Get/:With/:Set/:Apply/:Subscribe류는 전부 대문자, canExecute/
bindLifetime/isState류/Dispatch.process류/Brand.set류는 전부
소문자)가 이미 예외 없이 이 규칙을 따르고 있었음이 확인됨. 유일하게
애매해 보였던 Modifier.Override(mod1, mod2, ...)(콜론 아니고 dot-access
인데 대문자)도 규칙 위반이 아니라 세 번째 하위 규칙으로 설명됨 — 콜론
메서드는 아니지만 Modifier 타입 자신의 네임스페이스에 달린 정적
결합 함수라 "그 프리미티브 타입 고유의 공개 어휘"라는 점에서 생성자/
메서드와 같은 부류. 반대로 Dispatch.process/Brand.set이 소문자인
이유는 Dispatch/Brand가 애초에 Type(args) 생성자가 없는 프리미티브가
아닌 내부 엔진/레지스트리라서. 최종 판단 기준: "이 이름이 특정
프리미티브 타입 하나의 전용 소유물인가?" — 그렇다면 대문자, 아니면(여러
타입에 걸친 범용 유틸이거나 비-프리미티브 엔진 소속) 소문자. base/ architecture.md의 "코드 스타일 — 네이밍 케이싱" 절 신설.
같은 세션 후속 — module-lifecycle-plan.md의 "열린 질문" 절이 stale로
방치돼 있던 것을 사용자가 직접 발견. 문서 상단 "상태" 줄은 이미
"확정되어 승격됨"이라고 말하는데 그 아래 "열린 질문" 절은 2026-08-04
당시 그대로 남아있었음 — 그중 "프로바이더 인터페이스 시그니처 미정"/
"네이밍 미정(provider/processor/plug)" 두 항목이 사실 그 뒤 Handler
계약 확정으로 이미 풀려 있었는데 이 문서에 반영이 안 됐던 것. 원문은
남기고 각 항목에 해소 표시+포인터 추가, 절 제목도 "열린 질문이었던 것 —
전부 해소됨"으로 정정. 새 결정 아니라 순수 동기화.
다음 세션이 할 일: 안 바뀜(ROADMAP.md M0부터) — 이번 세션도 순수
설계/문서 정리라 M0 착수 우선순위 자체는 그대로. 위 2026-08-08 첫 세션이
남긴 "M0/M2 스파이크 검증 목록"에 새로 추가되는 항목 없음.