# 모듈 라이프사이클 — 프로바이더 패턴, bind/store는 누가 구현하는가 (착수 전) **상태**: research — 방향은 있지만 "누가 store를 구현하는가"는 사용자 스스로 "진짜 애매한 지점"이라고 남긴 미해결 항목. 원본: `.claude/initreq/raw-userinput.md` "넘버 바인드는 누가 처리?" / "모듈은 스코핑 되는가" / "pluggable 하다면 해당 플러그를 초기화하는 건 누구 몫?" / "다시 돌아와서… bind는 누가 어떻게 구현" / "스토어는 누가 구현해…" 절. 확정된 상위 결정은 `base/architecture.md` 12~14번 항목(멀티 백엔드, 싱글톤 모듈, 팩토리 초기화) 참고 — 이 문서는 그 안의 세부 미해결 사항만 다룸. ## 넘버 바인드(숫자 프로퍼티 등)는 누가 처리하는가 Slot과 맞물려서 잘 생각해서 구현해야 하는 부분. **기울어진 방향**: mount가 처리하는 게 맞아 보이지만, 그러면 확장성이 있을지가 문제. 결론: **표준 구현체는 인터페이스만 두고, 실제 구현은 `quad-roblox` 같은 백엔드 서브패키지가 해당 인터페이스를 구현**. 런타임에 프로바이더로 Roblox를 주입받는 방향(반대로 "프로바이더로 base를 받는" 게 아니라) — 이유: 여긴 가상돔이 없어서, base 쪽이 "누가 실제로 그려주는지" 모르는 채로 있다가 Roblox 프로바이더를 주입받는 모양이 더 자연스러워 보임. ## pluggable 플러그 초기화는 누구 몫인가 RBVM처럼 `init namespace` 하나하나 부르는 방식은 별로(`base/lifecycle-pattern.md` 5번 항목에서 실제로 rbvm이 이렇게 되어 있는 걸 확인함 — `InitNamespace`/ `Registered`-가드/`NewLib` 3종 세트를 라이브러리마다 반복). 대신 **적절한 팩토리 함수 제공**: `InitRoblox(Module)` 식으로, 생성된 모듈을 뮤테이션할 수 있는 도구를 주고 사용자가 호출하도록. `base/architecture.md` 14번 항목과 동일한 결정 — 여기서는 "왜"만 보강. ## Bind는 누가, 어떻게 구현하는가 인터페이스 상 `bind`를 두고 이것도 pluggable하게 할지 고민 — 단 **1개만 존재할 수 있는 형태**로 구현하는 게 맞다고 기울어짐: 이미 bind 구현체가 있는데 또 init하려 하면 오류, 없는데 뭔가 생성해서 bind하려 해도 오류. 즉 "pluggable 슬롯이지만 유일하게 채워질 수 있는 슬롯" — 위의 `research/bind-system-plan.md`가 말하는 "여러 핸들러가 우선순위로 경쟁"하는 것과는 다른 층위: **핸들러 레지스트리 자체(그 배후의 실제 bind 구현/백엔드)는 유일해야 하고, 그 안에 등록되는 개별 핸들러들은 여럿+우선순위 경쟁이 맞는 모양.** 의존성을 부작용 식으로 주입해서 `quad-roblox` 바인드를 허용케 하는 건 괜찮아 보임(=`InitRoblox(Module)`가 하는 일이 바로 이 "유일 슬롯 채우기"). ## Store는 누구 몫인가 — 상당 부분 확정됨 **사용자 확인 완료**: base가 `LifetimeHandle` 추상화(생명주기/`Connected` 계산 속성)를 소유하는 게 맞다고 확정. 추가로 명확해진 것 — **store 바인드가 수행하는 "처리된 값을 다시 `process(inst,k,realv)`로 넘기는" 재실행 로직 자체도 base가 한 번만 구현**해야 함(모든 백엔드/핸들러가 각자 재구현하면 안 됨). 근거: "모든 곳에서 다시 구현하는 건 나쁘니까." → `research/ bind-system-plan.md`의 "확정된 디스패치 모델" 절이 바로 이 base 제공 로직. 부수적으로 확인된 것: - **Store 자체의 연산은 더 단순해져도 됨** — v1의 `:Add`/`:With`/`:Tween` 같은 이름 붙은 체이닝 연산(named modifier)은 명시적으로 안 만들기로 확정, 대신 일반 함수를 받는 형태로 통일(`base/store-semantics.md` 참고). "너무 verbose한 연산들은 오히려 일관성을 해친다"는 게 이유. - **여러 store 값을 묶어 유연하게 처리하는 방법**(`useEffect`류 dependency array)은 있으면 좋겠다는 요청 — API 시그니처는 미정, `research/ bind-system-plan.md`의 남은 열린 질문 참고. - `can execute store bind` 후킹 자체는 `Connected` 계산 속성으로 대체된다는 잠정 제안이 그대로 유지되고, 여기에 더해 **완전 소멸(Destroy) 시점엔 아무 처리도 필요 없다**는 원칙까지 확정됨(`base/lifecycle-pattern.md`) — 즉 이 질문은 "필요한가?"에서 "확정된 Connected 체크 하나로 충분하다"로 정리됨. - 여러 `isHandlable`이 되는 플러그를 매번 우선순위 순으로 스캔하는 비용은 여전히 실제 구현/벤치마크 단계에서 검증 필요 — 디자인 자체는 확정됐으므로 더 이상 사용자 자문 대상이 아니라 구현 검증 대상. ## 모듈 스코핑 (참고, 확정은 `base/architecture.md` 13번) 한 Lua 스레드에서 둘 이상의 모듈 분화체(Roblox+비Roblox 동시)를 쓸 일이 거의 없을 거라 판단, 지금은 싱글톤으로 두고 필요해지면 `New()` 추가. ## Quad는 스크립트인가 라이브러리인가 (확정, 참고용) 이전엔 Instance를 보조하는 역할이라 "스크립트"로 분류했지만, 지금은 확실히 "라이브러리" — 구조화되어 있고 데이터 타입이 존재함. 기능을 각자 따로 묶는 게 아니라 하나의 시스템으로 돌 수 있게(pluggable 하게 두자는 논리의 근거이기도 함). `base/architecture.md` 도입부와 동일 결정. ## 열린 질문 (`.claude/question.md`에도 취합) - **Store 책임 분리(base vs provider)는 확정됨** — 위 절 참고. 남은 건 실제 구현 단계에서 base의 `LifetimeHandle`/재실행 유틸 API를 정확히 어떻게 노출할지 정도(설계 방향 자체는 더 이상 열려있지 않음). - 넘버 바인드/프로바이더 인터페이스의 정확한 함수 시그니처(base가 요구하는 provider 인터페이스 계약)는 아직 미정 — 구현 착수 시 함께 확정. - **네이밍 미정(2026-08-04 보강)**: "프로바이더"라고 불러온 개념을 정확히 뭐라고 부를지("provider" vs "processor" vs 그냥 "plug") 아직 안 정함 — 실제로는 `isHandlable`로 받을지 말지 결정하고 우선순위대로 스캔되는 pluggable 참가자라는 점은 확정, 이름만 미정. - base 유틸(per-instance 상태 저장소, 생명 바인드 유틸)이 인터페이스만 두고 실제 구현은 백엔드 팩토리(`RobloxFactory(BaseModule)`류)가 뮤테이션으로 주입한다는 패턴이 확정됨 — 상세는 `research/bind-system-plan.md`의 "base 유틸은 인터페이스, 실제 구현은 백엔드 팩토리가 주입" 절 참고. 이 패턴을 중복 호출했을 때의 가드 동작(멱등 처리)과 모듈 스코핑(`New()`)의 관계는 여전히 열려있음.