# Store 의미론 — 부작용 허용, State 프리미티브 없음 **상태**: base — 확정된 설계 결정 두 가지. 원본: `.claude/initreq/raw-userinput.md` "store는 부작용을 허용함" / "state는 어떻게 구현하는가" 절. ## Store는 부작용을 허용하는 게 기본 디자인 부작용 없이(파라메터 패싱만으로) 쓰는 것도 물론 가능하지만, 라이브러리 차원에서 막지 않는다. 부작용 유무는 **사용자가 직접 문서화**하는 관례로 둔다 — 라이브러리가 순수성을 강제하지 않음. 다만 한 가지는 명확히 구분: **렌더 리턴 위에서 무언가를 observe하는 것은 그냥 부작용**이다 (`useEffect`와 유사한 것으로 문서화). 이건 "허용되는 부작용"이 아니라 "당연히 부작용"이라는 뜻 — 문서화 시 이 경계를 분명히 할 것 (`research/ purity-and-effects-plan.md`와 연결됨). ## 별도 `State` 프리미티브는 만들지 않는다 (기본값) 클래스 자신이 필요한 state가 있으면 그냥 클래스 안에서 `Store`를 만들면 됨 — Store는 부분집합으로 쪼개 전달하는 것도 충분히 가능하다고 보기 때문에, 굳이 "단일 값 저장용" State를 별도로 만들 필요성을 못 느낌. 나누고 싶으면 사용자가 알아서 나누면 됨(사용자 자유). **단서**: 구현하다가 실제로 State가 있는 게 더 편해지는 지점이 나오면 그때 추가할 수 있음 — 지금은 "필요성이 확인 안 됐다"는 판단이지 "절대 안 만든다"는 확정이 아님. 구현 라운드에서 이 판단이 바뀌면 이 문서를 갱신할 것. ## Store 값 설정 문법 — v1 인체공학 유지 (확정) **사용자 확인 완료**: Store 값 설정은 `__newindex` 기반(`myStore.key = value`)을 그대로 유지 — ProfileService 등 Roblox 생태계에서 이미 익숙한 관용구라 바꿀 이유 없음. 마찬가지로 다음 두 인체공학도 유지: - **괄호 생략(paren-less) 구조** — 필요 시 커링(`myStore "key"`처럼 문자열 하나로 register를 얻는 v1 스타일)을 계속 허용. - **`:` 체이닝** — 값을 바꾸는 연산에 한해 체이닝 문법 허용(`base/ architecture.md`의 "함수지향 디폴트, `:`는 예외적으로만" 원칙과 일치 — 체이닝이 자연스러운 곳 중 하나가 바로 이 store 값 변경). `base/architecture.md`의 "복사 구현 지양, 팩토리 함수로 대체" 원칙과 함께 읽을 것 — v1의 문제는 metatable 체이닝으로 매번 새 테이블을 할당하며 "불변 빌더"를 흉내낸 것이었지, `:` 체이닝 문법 자체나 커링 문법 자체가 아니었음. v2는 문법 인체공학(사용자가 좋아하는 부분)은 유지하되 내부 구현(체이닝이 아니라 팩토리 함수)만 바꾼다. ## 여러 스토어 값을 묶어 처리하는 것 (dependency array) — 연구 필요 `useEffect`처럼 여러 store 값을 디펜던시로 묶어 파생값을 계산하고 싶다는 요구가 있음(v1의 `myStore "a,b"` 콤마-조인 문자열 방식은 폐기 대상 — `base/quad-v1-architecture.md`의 "문자열 DSL" 문제점 참고). 단, **v1의 `:Add`/`:With`/`:Tween` 같은 이름 붙은(named) 체이닝 연산은 만들지 않기로 확정** — 대신 일반 함수를 받아 처리하는 쪽이 일관적이라는 판단. 구체적인 API 모양(`Store.Combine({a,b}, function(a,b) ... end)`류)은 아직 미정 — `research/bind-system-plan.md` 참고.