quad/.claude/archive/observer-cleanup-contract-rejected.md
qwreey 911ab559ea
fix(base): 코퍼스 전체 stale 마커/모순 감사 및 무효화된 인라인 서사 archive 이전
이미 해소된 결정이 미해결로 표시되거나 문서 간 모순되던 항목 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
2026-08-09 16:36:59 +09:00

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)fnnil | () -> ()를 반환하면, 다음 재실행 직전에 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 참고).