이미 해소된 결정이 미해결로 표시되거나 문서 간 모순되던 항목 7개 파일 수정, 뒤집힌/무효화된 설계 서술이 정정 표시만 붙은 채 본문에 남아있던 곳을 기존 archive 컨벤션대로 이전(quad2-try 리서치, Observer cleanup 계약, keyed collection state method, debug channel ReplicatedStorage). CLAUDE.md에 세션 로그 반영. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYfAz3BsaTrmMM8hnzn6mj
2.1 KiB
[기각됨] Observer 자체에 React useEffect식 cleanup 반환 계약 추가
기각 일시: 2026-08-07 여섯 번째 세션. 현재 유효한 설계: base/ effect-plan.md "Effect와 Observer의 관계" 절 — Observer의 기본 계약은
재실행 신호만 주고 cleanup은 클로저로 직접 처리, 자동 cleanup 배선이
필요하면 opt-in 상위 계층인 Effect(fn, state?)를 쓸 것. 이 파일은 더
이상 능동적으로 참고할 필요 없음(구현에 안 씀) — "왜 Observer 자체에
cleanup 계약을 안 넣었는가"가 quadnomicon(프레임워크 설계자용 심화
콘텐츠) 소재로 가치 있어서 사유를 보존해둔 것.
무엇을 검토했었나
React useEffect류 패턴 — state:Observer(fn)의 fn이 nil | () -> ()를
반환하면, 다음 재실행 직전에 quad가 그 반환값을 자동으로 호출해주는 안.
기각 이유
클로저 업밸류로 이미 쉽게 되고 잘 작동함:
local lastConn
state:Observer(function()
if lastConn then lastConn:Disconnect() end
lastConn = ...
end)
Observer 자체가 이걸 대신 배선해줘야 할 이유가 약함 — 반환값을 잡아뒀다가 다음 실행 전에 불러주는 기능을 Observer 코어에 넣으면, 그 계약을 안 쓰는 대다수 사용처까지 복잡도가 늘어나는데 클로저로 이미 공짜로 되는 걸 다시 API 표면으로 만드는 셈.
왜 완전히 헛수고는 아니었나 — Effect 설계와 상충하지 않음
이 기각과 이후 확정된 Effect(fn, state?) 설계는 상충하지 않는다 — 그때
기각한 건 "Observer 자체에 이 복잡도를 넣지 말자"였지 "이 패턴 자체가
무용하다"가 아니었음. 자동 cleanup 배선이 필요한 사람만 opt-in으로 쓰는
별도 계층(Effect)으로 분리해 얹었을 뿐, Observer의 기본 계약(재실행
신호만, cleanup은 클로저로 직접)은 그대로 가볍게 유지됨 — Effect가
내부적으로 state:Observer(...)를 조합해 이 패턴을 상위 계층에서 정확히
구현한다(base/effect-plan.md 참고).