# 구현 전 QA 5라운드 — 사용자 회신 원문 (2026-08-21) **이 파일은 회신 원문 그대로의 기록이다** — 처리 결과의 소스는 `pre-implementation-qa-round5-followup.md`. 4라운드와 같은 구성 (문항지 / 회신 원문 / 처리 결과 3파일). --- ### DE-7 _detached 를 모든 slot 이 가져야하나는 의문이 듦. 내부적으로 getOrSet 해서 detached 를 리턴해주는 유틸을 만들고, nilable 해도 되지 않나라는 생각. destroySlotTree 가 _detached 를 인덱스 해보고 nil 아닌지 보고 돌리는게 더 나아보이는데, 테이블 생성 비용을 모든 slot 이 가져야하나는 의문. List 슬롯에서만 작동하는것인데, 너무 광범위하지 않은가? if 확인으로 nil 이면 스킵이 훨씬 싸게 먹히지 않는가? 순수 구현 상 아무 문제 없겠지만, 단순 최적화 문제. 최적화에 드는 비용이 거의 없는데, 안 할 이유가 보이진 않음. + 아무것도 없는데 Detach 를 보내면 어떻게 되느냐. prev 없음을 유저가 추적해야하는가, 아니면 detach 를 그냥 prev == nil 일 때 던지면 무시해주느냐 prev 가 마운트 상태에서(Detach 안 함) 다시 prev 를 던지는것은 이번 변경으로 인해서 여전히 문제 없이 잘 작동하는가 ### DE-9 error 하면 된다. KeyGone 을 받은 요소는 오직 데이터의 파괴 또는 detach 를 통해 다시 나오는 경우를 위한 캐싱 이외의 새로운 마운트나 생성을 거부한다. ### DE-11 맞다. 문서화에서만 유의하면 되는 부분. 단순 삽입/삭제가 빈번한 경우를 위한 최적화 일 뿐. 그 이상의 동작을 돕지 않는다. ### DE-13 _detachCleanup 이 정확히 어떤건지 모르겠음. _detached 에 들어가게 될 대상을 말하는것인지? 아니면 detach 된 요소들이 나중에 정리되어야할 때인지? 나중에 detach 했던 요소들을 청소하는것이라면, 소유한것이면 죽이는게 맞긴 하다. 다만 주의해야할 부분이 보인다. 애초에 unowned 의 state 로 받은것은 더이상 가지고 있지 않는다. detach 에 들어가있지도 않는다. 외부로 반출된 것이라 다시 들고와서 자기 자신에 붙이지 않음. 즉 detach 가 unowned 에 대해서 수행되면 prev 가 나중에 nil 이 되는것이다. 그래야 state 에서 내부를 교체했을 때, 이전 요소를 안 건들이게 되는것이라 생각하는데, 내 생각이 잘못 흐른건지 검토해달라. ### DE-17 주의 할 점은, state 가 slot 에 바로 안 오기 때문에, updateFn 이 state 를 던져도 싱글 slot화 된다. 그리고 owned = false 가 되는건 이 싱글 슬롯 안 1번째 객체에 대해서 적용이다. 나중에 새로운 state 같은게 나온다면, 이전거는 prev 로 updateFn 이 받으니 그걸 어떻게 처리할지는 updateFn 의 몫. 특히 slot 래핑 안 된 상태로 받아야하는가도 생각해보아야한다. prev 는 이전에 던진 그대로 주는것이므로. 그리고 이전과 같은 state 를 던지면 멱등으로써 새로운 slot 을 만들지 않고 그대로 두는것도 여전해야한다. ### DE-22 의도가 맞다. ### AS-5 activateList 도 결국 상위에 setlength 를 하는것 아닌가? 게이트가 blocker 없이는 호출되지 않는지 확인 필요 ### DC-6 더 정확히는, 슬롯을 뽑아냈을 때, 이전에 렌더된 요소들은 여전히 layout order 등을 위해 offset을 연결해두고 있다. 이 상황에서 아에 다른 값을 slot.Offset 으로 쓴다는것 자체가 나중에 포탈에서 깨지는 부분을 생성한다 ### DC-11 필요 이유를 모르겠음. length 업데이트를 위한것임? ### DC-14 사실, 외부 입장에서는 그럴 방법이 없어보인다. crud 가 list 시에는 더이상 불가능해지기 때문. ### DC-19 rawAdd 에서도 필요한가는 모르겠음. 목적이 다르지 않나? ### SS-2, SS-3 단순히 각 state 에, 이전 emit 을 발생시킨 발행 unique table 를 넣는건 어떤지 고민중. source 에서만 발행되고 emit 상 전파된다. 지금 보이는 문제로는 A -> B --> D -> C -| 상황에서 결국 dfs 로 순회되어서 D 에 먼저 A 소스의 emit 신호가 온다. C는 아직 받기 전. invalid 하지 않아서 바로 캐시가 읽히고, 그대로 D에 캐시에 쓰인다. C의 변경으로 다시 emit 되긴 하지만, 이걸 잡을만한 방법이 없어보이진 않는다. 이런 문제를 전부 쉽게 푸는 방법이 존재하는데, emit 시 unique 한 테이블 하나를 전파하고 그 테이블 안에 count 값과 invalid 플래그가 들어간다.. 각 source 는 해당 테이블을 가지고 있다가 emit 된다면 invalid=false count=최신으로 값을 로 바꾼다. with 에서는 여럿 받은 곳에 대한걸 관리하도록 둔다. -> 생각하다 위쪽껀 이상했음. 이러면 모든 발행된 unique 를 들고 count 를 관리해야한다 아니면 반대로 count 부분만 담는 테이블을 만들고 연결하는건 어떤가? unique 자신의 실제 인덱스와, source 의 count 와 비교해서 일치해지는가를 본다. 만일 파이프 뒷 요소로 get 되어진 경우 최상위 소스에서 해당 유니크를 가져와 덮어도 된다. -> bfs 도 생각했는데, 순서를 꼬아두면 문제가 생긴다. 재정리: 차라리 이렇게? State() sourceList <- { [source:weak] -> count } weak 로 영향받는 source 들을 담는다. 앞단 요소에서 복사, with 시 합친다 rawInvalid <- 단순 emit 시에 바로 false 된다. 캐싱 invalid <- rawInvalid 캐시를 보고 true 라면 sourceList 를 보고 계산 필요 상태인지 확인한다 더 생각해볼 이야기라 백로깅이나 리서치에 들어가야할듯. Get 이 항상 최신 상태를 가져온다라는 말이 여기서 무력화되는 부분이라 생각이 필요해보인다. 어차피 emit 단순히 전파는 false 이라 연산 비용이 없어 잘 전파되고. 복합 state 상태를 잘 관리해주는게 나아보인다. 대부분 옵저빙을 하여 state 를 읽지, 폴링해서 get 하는 경우도 잘 없으므로 문제 있는 구현으로 안 보인다. 폴링을 위해서는 Apply(Realtime()) 같은 슈거를 주면 된다. 옵져버로 항상 get 하고 value 를 실시간으로 읽을 수 있게 해주는것. 단순하게 Ref 로 변환해주는 등의 작업을 하는 슈거를 줘도 된다. 비용은 다소 한정적으로 보인다. 해시 for은 이미 빠르고, Source가 중간중간 느는게 아니라 처음 시작점이라 수 자체가 적다. 2~4개에 대해 인덱싱 하는 정도라 충분히 가벼워보이는 단일 for 로 해결이 되는것으로 보임. emit 은 이제, 발행시킨 source 와 count 를 전달하기만 하면 된다. count 를 쓰기 싫다면 단일 테이블을 써도 되는 부분. [source:weak] -> {} 선제 최적화라기 보단 확실히 정해진 동작으로 승격하는 일로 보이는데 어떻게 생각하는가? ### LC-3, LC-4 무슨말인지 모르겠다. 애초에 Slot effect 나 다른 요소들을 소유할 수가 없다. 심지어 내 생각으로는 slot owned 가 canBound 에 들어갈 이유가 있나? 모르겠다 왜냐면 실제 observer/effect 는 실제 inst 에 불림. slot in slot 에서 slot 을 유지하는건 이미 slot 의 강참조 배열이 해결해주는데, 우리가 왜 slot 을 소유 대상으로 둘 수 있게 한거였는지 다시 생각해봐야할 부분인듯? ### EF-3 예 ### AT-1 (inst, groupValue) → k 이면 충분하다. group 에 따라 key 가 따로 생성되므로 다른 그룹에 대해서는 잡을 필요가 없고, 그건 key->name 이 유일성을 검증해준다. {a,a} 는 단순 그룹이 이미 할당된 키가 있나를 보기만 위함임. AT-2 도 같이 닫는다 ### TW-2 Mapped 로 확정 CR-2 도 해결됨 ### DT-4 그렇다. 이러면 스로틀/디바운싱에 Observer 를 걸어야하는데, 이 옵저버의 emit 이 먼저이냐 후행 Blocker 로 생성된 요소의 emit 이 먼저이냐가 문제되기 때문에 Blocker/Observer 가지고는 구현 못 한다. 순서를 보존해야한다는 전재가 생기는데 중간이 비어 해시가 되면 이를 전혀 못 지키기 때문. Gate 가 emit 에 중간에 가로채서 넘길지 말지 처리를 해줄 수 있게하는 방법을 제공하는게 맞다. 그리고 이 API가 비공개일 이유는 없어보인다. ### CR-3 게이팅 먼저. 게이팅을 base 에 만들 준비를 해야한다. 실질적 모양 정의가 필요함 생각 상 새로운 state 가 나오지는 않고, Blocker 와 유사히 동작한다. 내부 배선 상 이렇게 되면 되는거 아닌가 생각중. Gate(function(emit) ^-- 위 emit 은 언제든 사용 가능 return function () <- 상위 emit 시 발생. 위 emit 을 쓸지 말지는 자유 end end) 다만 프리미티브 명을 Gater? 뭔가 이상하게 들어간다는게 약간의 문제. ### CR-4 부모가 죽기 전까진 detached 정리가 안되니 그건 맞다. + Effect 가 지금은 Ref에 대해서 수행될 수가 없다. 단순히 Effect(, ...) 를 만들고 ... 요소를 With 으로 합치는게 아니라 여러 요소에 대해서 Observe/Callback 하는게 어떻겠냐는 생각이 드는 지점. 처음 분기는 Blocker() 의 다른 사용법을 통해 막는다. 그게 더 나은 구현으로 보이는중. + 확인할 부분이 있다. state -> Slot single { Slot } 모양이 될 때 부모 Slot 이 length 를 잘 따라가는가? 아마 그렇다고 보는데, 정확한지 봐야한다. + 뽑는것은 자유롭지만, Slot 이 들고있다 죽는건 죽어야하는데. 그 처리가 영향을 받았는지 궁금함. 즉 Frame { Slot { State(Frame) <- 여기 바인딩은 상위 Frame 이 죽으면 같이 죽음. } } 이건 Effect 쪽에서 뭔가 처리해줄 수 있는게 아닌게, 엔진 자체가 recursive 호출로 전부 죽이는게 일반적이기에 우리가 빼줄 수 있는 요소도 아니고, 같이 죽는게 의도 동작이기 때문. 따라서 State 에서 무언가 마운트 된 요소를 뽑아낼 때, 부모가 죽었다면 이미 죽은 요소가 된다. 이건 의도 동작인데, 언급이 되어있나 모르겠음.