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.
4.1 KiB
4.1 KiB
2026-08-09 일곱 번째 세션 — Slot:List의 data:Observer(fn) 구독도
마운트 시점 lazy bindLifetime으로 확정 (Destroy 후 재실행 gap 해소)
사용자가 "Slot이 마운트된 대상이 Destroy로 죽으면 updateFn 재실행이
canExecute로 막히고 있는 게 맞냐"고 질문하며 시작 — 확인 결과 두 메커니즘이
다른 상태였음: Dispatch.setLength(Length/Offset, 여섯 번째 세션 확정)는
이미 정확히 그렇게 돼 있었지만(Slot 마운트 시점에 bindLifetime(inst,observer)),
Slot:List의 data:Observer(fn) 구독은 :List() 호출 그 자리에서 즉시
만들어져(inst를 모르는 시점) bindLifetime이 전혀 안 걸려있던 실제 gap —
사용자가 정확히 캐치함. 사용자가 이어서 "실제로 Instance에 바인드되려 시도될
때(=마운트 시점)로 구독 자체를 lazy하게 미루면 되지 않냐"고 제안, 검증 후
확정. base/slot-plan.md(:List의 "구현"/"구독 시점" 절 재작성 +
"base/roblox 패키지 경계" 절 보강)/ROADMAP.md(M6)에 반영 완료:
Dispatch.setLength가 이미 쓰던 패턴을 그대로 재사용, 새 메커니즘 없음.:List(data,updateFn,keyFn)는 이제 설정만 저장하고 반환 — 실제data:Observer(fn)구독과 최초reconcile은 Slot 컨테이너 자신이 마운트되는 순간(Dispatch/Slot.luau의process(inst,k,self),self._mounted를 세팅하는 바로 그 자리)에activateList(self,inst)가 수행.:List()가 마운트 이후에 불리는 경우 —self._mounted면 즉시 활성화로 확정(사용자 확인, 세 가지 대안 중 1번). 마운트는 1회성 이벤트라 순서가 뒤바뀌면 그 이벤트를 못 기다리므로,:List()가self._mounted를 직접 확인해서 이미 참이면 그 자리에서 즉시activateList— 호출 순서 제약을 새로 추가하지 않음.- canExecute와 "등록 즉시 1회 실행"의 관계를 사용자가 직접 짚어 확정:
data:Observer(fn)등록 시점(=bindLifetime호출 이전)의 최초 1회 실행은canExecute/Subscribed게이팅과 무관하게 무조건 일어남 — 이 시점엔 아직Subscribed가 안 세팅돼canExecute를 물으면 거짓이겠지만, 애초에 최초 실행은 게이팅 대상이 아니라서 상관없음(Dispatch.setLength가 이미 "등록 즉시 1회와 겹쳐도 무해"로 같은 구조를 갖고 있었음).bindLifetime은 등록 직후에 걸려 이후 재실행만 게이팅. - Destroy 이후 "재실행 막기"+"관측 자체를 관두기"가 새 코드 없이 한 번에
해결됨 —
instDestroy 시gcconn이 죽어canExecute가 거짓이 되고 향후 재실행이 no-op되는 동시에,gchold가Relate(inst)(weak-keyed) 아래 있어서inst가 죽으면 그 안에 강참조로 잡혀있던 Observer/클로저 (mounted/userdata/keyIndex포함)가 전부 GC 대상이 됨 — 명시적 구독 해제 코드가 안 필요함,lifecycle-pattern.md의 "정리는 기본적으로 GC에 위임" 원칙 그대로. - 부수 관찰(메모만, 설계 아님): 사용자가 "
Relate로 마운트된 대상을 weak하게 구할 수도 있겠다"고 언급 —bindLifetime이Relate(inst)기반이라 나중에 "이inst에 지금 뭐가 붙어있는가" 역조회가 같은 저장소로 가능해 보임, quad-debug 그래프 UX와 맞닿을 수 있음. 지금 설계 안 함, 필요성 확인되면 그때.
다음 세션이 할 일: 안 바뀜(ROADMAP.md M0부터) — 이번 세션도 순수
설계 확정이라 M0 착수 우선순위 자체는 그대로.