InitRoblox(Module) backend 주입 패턴을 quad-base 자기 내부(Dispatch 등)에도 대칭 적용 — 각 서브시스템이 InitXxx(module)로 module을 뮤테이션. 서브시스템 간 호출 순서 문제는 각 InitXxx 파일 톱레벨에 Relate() 하나를 두고 module을 weak key 삼아 인스턴스별 완료 여부를 기록해 require처럼 멱등하게 만들어 해소(relate-plan.md 체크리스트에도 용례 추가). module-lifecycle-plan.md에 "New()의 내부 구성" 절 신설, architecture.md/dispatch-core-plan.md/ ROADMAP.md(M1 체크리스트)에서 상호 참조. 핸드오버 감사 루프 4라운드(무발견 1회로 수렴) — 라운드 1~2는 절 인용 사각지대·상호참조 누락·SetWeak/SetStrong 일관성을 잡았고, 라운드 3~4는 그 수정 자체가 남긴 커밋 개수/날짜 오기, 원문 인용 파라프레이즈 등을 추가로 잡음. 부수로 session/ 기록 공백(2026-08-18/19 다수 커밋에 원문 누락)을 발견해 이번 세션분만 session/2026-08-19-01-*.md로 남김 — 과거 공백 처리는 사용자 확인 대기. Co-authored-by: qwreey <me@qwreey.moe>
7.7 KiB
2026-08-19 — New()의 내부 구성: InitXxx 팩토리 체이닝 + Relate 기반 멱등 Init 가드
요청: Quad.New()가 실제로 어떻게 구현돼야 하는지에 대한 사용자
아이디어 검토 요청으로 시작 — 결론까지 나서 base/에 반영, 이어서
핸드오버 감사 루프와 세션 기록 공백 점검까지 같은 세션에서 처리.
1. 제안 — New()를 InitXxx 팩토리 체이닝으로
사용자 원문: "New() 가 실행되면 Quad 를 만드는 함수가 있는것으로 처음부터 구현하는게 맞음. ... New 결과 안에 .New 함수를 넣어줌. 즉, 생성형식 자체는 비싱글톤이고, Dispatch 같은것도 Init(module) 을 받는 함수로써 ... module.Dispatch = ... 형식들로 구현되고 ... 재익스포트식으로 구현하겠다는 이야기였음. 처음부터 InitModuleName 식으로 구현하여 팩토리를 쌓아 모듈을 리턴하는 방식으로, quad v1 의 방식을 가져와봄직 하다는것."
조사: 기존 base/architecture.md 13번("모듈은 기본 싱글톤, New()는
추가 인스턴스가 필요할 때만")과 14번("pluggable 초기화는 팩토리 함수로"),
module-lifecycle-plan.md가 이미 InitRoblox(Module) 형태의 backend 주입
패턴을 확정해뒀다는 걸 확인 — 이번 제안은 그 패턴을 quad-base 자기
자신의 내부 구성(Dispatch 등)에도 대칭 적용하자는 것이라 새 설계가
아니라 기존 원칙의 자연스러운 확장으로 판단. lifecycle-pattern.md가
거부한 rbvm InitNamespace 패턴(소비자가 라이브러리마다 수동으로 init을
부르는 것)과도 안 겹침 — 여기선 New() 하나만 외부에 노출되고 내부에서만
InitXxx(module)를 부름.
결론: 채택 추천 — module = {New = New} 자기참조도 이미 확정된 결정과
정확히 일치, type Dispatch = InitDispatch.Dispatch 재익스포트만 실제
Luau 동작 확인 필요하다고 남겨둠.
사용자 확인: "그거 타입 익스포트 잘 됨. 구체화 반영해줘." → 실측
확인됐다는 뜻으로 받아 module-lifecycle-plan.md에 "New()의 내부 구성"
절 신설, architecture.md 13번에서 포인터 연결.
2. 정제 — Init을 require처럼 멱등하게
사용자 원문: "Init 은 require 처럼 생각 가능한듯. Init 여러번은 한번만 작동하게 자신 모듈 최상단에 Relate 를 (함수 안 아님. 클로저 바깥) 놓고, 자신 모듈의 init 여부를 저장해. 그리고 한번만 작동하도록 두고, 자신 init 에선 필요한것들을 init 해줘. 디펜던시 느낌인거지. ... 맨 바깥 quad-base 진입점의 New 에선 모든 Init 을 그냥 실행해도 돼."
이게 1절 문서화 때 "구현 단계에서 정할 것"으로 남겨뒀던 "서브시스템 간
InitXxx 호출 순서 의존성" 문제를 실제로 푼다 — 각 InitXxx 파일이 자기
톱레벨(클로저 밖)에 local relate = Relate()를 두고 module을 weak key로
"이미 이 인스턴스에 Init됐는지"를 기록하면, 의존하는 쪽이 자기 의존성을
직접 호출해도 중복/순서 걱정이 없어짐(멱등) — require가 파일 단위로 하는
캐싱을, New()가 여러 module 인스턴스를 만들 수 있다는 차이 때문에
인스턴스 단위로 다시 구현하는 것.
relate-plan.md의 확정 API(Relate()/SetWeak/GetWeak/SetStrong/
GetStrong, "각 모듈이 자기 톱레벨에 Relate() 하나 재사용" 관례)와
정확히 부합함을 확인 — 새 메커니즘이 아니라 기존 프리미티브의 정확한
용례. module-lifecycle-plan.md에 반영, 순환 의존 대비를 위해 플래그를
실제 작업 전에 먼저 세우는 규칙도 같이 명문화.
3. 핸드오버 감사 루프 (2라운드, conventions.md의 "핸드오버 준비하고
커밋해" 절차)
바뀐 파일: base/architecture.md, base/module-lifecycle-plan.md,
base/dispatch-core-plan.md, README.md, ROADMAP.md.
라운드 1(quad-doc-auditor, agentId ad95c24230306ab0f) — 확실 3건 +
의심 3건 + 사용자판단 1건:
- 확실:
architecture.md의 "M0 스캐폴딩에 주는 함의" 불릿이 이미 InitXxx 절이 답한 질문을 여전히 미결정으로 서술 /README.md색인에 새 절 요약 누락 /module-lifecycle-plan.md의 "지금은 없음"이 날짜 없는 시한부 주장. - 의심:
_initializedBy상호 참조가 정의를 못 찾게 함(bind-system-plan.md누락) / GC 인과 서술이relate-plan.md의 "inst는 항상 weak" 규칙과 어긋나게 읽힘 /dispatch-core-plan.md가 새 절을 안 가리켜 상호참조 누락. - 사용자판단(문서만으론 못 정함, 이번엔 직접 판단해 처리): InitXxx 구조가
M0/M1 중 어느 마일스톤부터인지 →
ROADMAP.md의 "M0 — 스켈레톤 + 기술검증" 절 실제 내용(스파이크 전용, "진짜 마일스톤 아님")을 근거로 M1로 확정,ROADMAP.mdM1 체크리스트에 항목 신설.
전부 반영(위 6곳 수정 + M1 체크박스 추가).
라운드 2(agentId a1d60d10fc36621ed) — 라운드 1 수정 자체가 새 stale
2건을 만든 걸 발견:
architecture.md가 인용하던 "M0 스캐폴딩에 주는 함의"라는 절 제목 문구를 라운드 1 수정이 지워버려 절 인용 규약 사각지대(파일명 없는 같은 문서 내 인용이라doc-check.py가 안 잡음) 발생 → 원래 제목 문구를 불릿 맨 앞에 복원하면서 내용만 정정.- "위 'M0 — 스켈레톤 + 기술검증' 절 참고"가 실제로는
ROADMAP.md안의 절인데 파일명이 빠져 같은 문서 안인 것처럼 읽힘 →ROADMAP.md의 명시. - 추가로 "확실": 이 새 절 자체가 사용자 발언 3건을 인용하면서
session/2026-08-19-*.md포인터가 없음(이 문서가 그 포인터). - 의심:
relate-plan.md의 "언제 Relate를 쓰는가" 체크리스트에 새 용례가 안 실림 → 다섯 번째 불릿 추가. - 사용자판단: Init-완료 플래그 값(
true)을SetWeak/SetStrong중 뭘로 적을지가 문서 간 안 맞음 → boolean은 GC 대상이 아니라 실질 차이는 없지만relate-plan.md의 일반 규칙("다른 곳에서 안 붙잡는 값은 Strong") 기준SetStrong으로 통일.
전부 반영. 라운드 3은 이 문서 작성 이후 진행 예정(아래 미해결 참고).
4. 세션 기록 공백 발견 (사용자가 감사 진행 중 별도로 제기)
사용자 질문: "세션 기록들 요즘 왜 안 적어? ... 18일 자가 하나 뿐이네."
확인 결과 — git log엔 2026-08-18에 커밋 10개(QA 1~2라운드, 감사 루프
재설계, GitHub co-author 정책, git 원격 정책 등), 2026-08-19에 커밋 1개
(QA 3라운드)가 있는데, session/엔 2026-08-18 파일이 pre-implementation-qa-applied.md
하나뿐이고 2026-08-19 파일은 이 문서 이전엔 0개였다. 즉 QA
2라운드/3라운드(todos.md 00번이 상세히 서술하는, RC-1/RC-3/RC-4를 실제로
찾아 해결한 세션들)와 tooling/research 커밋 다수가 session/ 원문 없이
커밋됨 — 실제 공백.
한계: 이 세션은 그 과거 대화의 실제 트랜스크립트에 접근할 수 없다(커밋
메시지와 현재 파일 상태만 볼 수 있음) — session/의 정의 자체가 "시행착오
포함 원문"이라, 원문을 못 본 채로 "raw log"를 지어내면 오히려 그 자체가
허위 기록이 된다. 그래서 이 문서는 이번 세션분만 원문으로 채웠고,
과거 공백(08-18 QA 2/3라운드 등)을 어떻게 처리할지는 사용자에게 별도로
물어야 함(요약만 session-summary.md에 사후 추가할지, 아예 공백으로
인정하고 넘어갈지 등 — 이 문서 자체가 그 판단의 근거 자료).