research: attachSlot 분해 — 일괄 마운트 차이 검토, 판단을 추천으로 갱신
사용자가 짚은 "물리 마운트가 관측 이후 일괄로 밀린다"는 차이를 따져본 결과 감수하는 비용이 아니라 개선이라는 결론. - 마운트 순서 자체는 안 바뀐다(둘 다 깊이 우선 같은 순서) — 바뀌는 건 각 Parent 대입 시점에 부기가 얼마나 완성돼 있는가뿐. - 그 차이를 실제로 관측하는 주체가 있다: Parent 대입이 ChildAdded/ DescendantAdded를 동기 발화시키므로 사용자 핸들러가 마운트 도중에 끼어든다. 현행은 A의 ChildAdded 시점에 inner.Length가 0이고 뒤 형제 offset도 stale인 미완성 스냅샷을 보여주는데, 분해하면 첫 발화 때 서브트리 전체가 최종값이다. slot.Length 구독자도 0→최종 두 번이 아니라 최종값으로 한 번 발화. - "합치는 거대 함수"는 만들어도 목적을 못 이룬다 — 완전 병합은 자식 길이를 그 자식 재귀가 끝나야 알므로 C6를 못 지키고(그게 지금 코드), 부분 병합은 인터리브는 유지하지만 부모 레벨 C7 위반이 그대로 남는다. 실질 선택지는 (A) 인터리브+자기교정 / (B) 분해+일괄 둘뿐. - 부수 이득 둘: Blocker가 materialize만 감싸게 되어 "배치 등록 게이팅"이라는 정의와 코드 범위가 일치하고, mountSlotTree가 순수 walk라 일괄 삽입이 유리한 백엔드(웹 DocumentFragment 등)가 그 함수 하나만 갈아끼울 수 있는 seam이 생긴다. 판단을 "약한 추천"에서 "추천"으로 갱신 — RC-1/RC-3/RC-4가 전부 한 함수 안의 줄 순서를 잘못 잡아 난 버그였는데, 분해하면 C2/C3/C7이 함수 경계로 강제되어 그 실수 클래스가 구조적으로 사라진다는 사용자 지적이 결정적. 다만 M6 착수 전 실제로 짜보며 확정해도 늦지 않다는 판단은 유지. Co-authored-by: qwreey <me@qwreey.moe>
This commit is contained in:
parent
6fd93c6dc2
commit
448b961e7f
1 changed files with 87 additions and 2 deletions
|
|
@ -184,8 +184,8 @@ R1(부모 등록)까지 따로 떼는 안. `Dispatch.drive`의 최상위 배열
|
|||
## 5. 지금 상태 요약
|
||||
|
||||
> **[2026-08-21 갱신] 사용자 판단으로 (B) 방향 + "공개 표면은 안 쪼갬"까지
|
||||
> 좁혀졌다** — 구체안은 아래 **6절**이 최신이고, 이 절과 3절은 거기까지 온
|
||||
> 경로다.
|
||||
> 좁혀졌다** — 구체안은 **6절**, "물리 마운트가 일괄로 밀리는" 차이에 대한
|
||||
> 검토와 판단 갱신은 **7절**이 최신이고, 이 절과 3절은 거기까지 온 경로다.
|
||||
|
||||
- **확정된 건 없다.** `base/slot-plan.md`의 단일 `attachSlot`이 여전히 정본.
|
||||
- **급하지 않다** — (A)로 두어도 동작은 맞고(자기 교정), M2/M3 착수를 막지
|
||||
|
|
@ -321,3 +321,88 @@ end
|
|||
**반대로 안 쪼갤 이유**도 정당하다 — 동작이 지금도 맞고(자기 교정), 순회가
|
||||
하나 늘며, 확정된 의사코드를 건드리는 변경이다. **M6 착수 시점에 실제로 짜보며
|
||||
정해도 늦지 않다.**
|
||||
|
||||
---
|
||||
|
||||
## 7. "물리 마운트가 일괄로 밀린다"는 차이 — 손해가 아니라 이득 (2026-08-21)
|
||||
|
||||
**사용자 관찰**: *"얼마나 nested 든, 하나 마운트되고 하나 마운트되고… 각
|
||||
객체들이 `Parent = inst` 되어가며 피지컬에 붙어가는 일자 진행인데, 이건 관측
|
||||
이후 일괄 등록이라는 차이가 있는듯 … 그러나 이런 사소한, 문제를 야기하기 어려운
|
||||
동작을 원래와 동치시키기 위해 디버깅이 어려운 함수를 만드는건 옳지 않아보임."*
|
||||
|
||||
**결론에 동의한다. 그리고 그 "차이"는 감수하는 비용이 아니라 개선이다.**
|
||||
|
||||
### 7-1. 마운트 **순서**는 안 바뀐다 — 바뀌는 건 부기와 섞이느냐뿐
|
||||
|
||||
`outer { A, inner { B, C }, D }` 기준:
|
||||
|
||||
| | 현행(인터리브) | 분해(일괄) |
|
||||
|---|---|---|
|
||||
| `Parent` 대입 순서 | A → B → C → D | A → B → C → D (**동일**) |
|
||||
| 각 대입 시점의 부기 상태 | 부분적 — A가 붙을 때 `inner.Length == 0`, outer의 뒤 offset은 아직 stale | **전부 완결** |
|
||||
|
||||
두 방식 다 `_elements`를 깊이 우선으로 같은 순서로 훑으므로 **관측 가능한
|
||||
마운트 순서는 동일**하다. 달라지는 건 "그 시점에 부기가 얼마나 완성돼
|
||||
있는가"뿐이다.
|
||||
|
||||
### 7-2. 그 차이를 실제로 관측하는 주체가 있고, 분해 쪽이 더 정확하다
|
||||
|
||||
Roblox의 `Parent` 대입은 **동기적으로 `ChildAdded`/`DescendantAdded`/
|
||||
`AncestryChanged`를 발화**시킨다. 즉 사용자 핸들러가 마운트 도중에 실제로
|
||||
끼어들어 상태를 읽는다.
|
||||
|
||||
- **현행**: A의 `ChildAdded`가 뜰 때 `inner.Length`는 아직 `0`이고, `outer`의
|
||||
뒤 형제 offset도 아직 안 밀려 있다 — **완성 전 스냅샷**을 보게 된다.
|
||||
- **분해**: 첫 `ChildAdded`가 뜰 때 **서브트리 전체의 `Length`/`Offset`이 이미
|
||||
최종값**이다.
|
||||
|
||||
`slot.Length`를 구독하는 사용자 State/Observer("n개 검색됨" 라벨 등)도 같다 —
|
||||
분해 쪽이 **한 번, 최종값으로** 발화한다(현행은 `0` → 최종으로 두 번).
|
||||
`PostRef`가 "자기 아래는 전부 끝난 뒤"를 보장하는 것과 결이 같아진다.
|
||||
|
||||
**즉 원래 동작을 보존할 이유가 약한 정도가 아니라, 원래 동작 쪽이 덜 정확하다.**
|
||||
|
||||
### 7-3. "합치는 거대 함수"는 애초에 목적을 못 이룬다
|
||||
|
||||
*"액티베이션 재귀와 실측시 마운트를 합치는 거대한 함수를 만드는게 아닌이상
|
||||
해결하지 못할 문제"* — 맞는데, **그 거대 함수를 만들어도 안 풀린다.** 두
|
||||
변형을 다 따져보면:
|
||||
|
||||
- **완전 병합(측정하면서 그 자리에서 마운트)** — 자식의 최종 길이는 그 자식의
|
||||
재귀가 **끝나야** 알 수 있으므로, 자식을 마운트하는 시점엔 아직 자기 길이를
|
||||
모른다. **C6를 못 지킨다** — 그게 정확히 지금 코드(= `Length=0`으로 등록 후
|
||||
자기 교정)다. 새로 얻는 게 없다.
|
||||
- **부분 병합(자식마다 `materialize` → 바로 `mount` → 다음 형제)** — 실제로
|
||||
가능하고 인터리브도 유지된다. 하지만 **자기 길이를 부모에게 등록하는 건
|
||||
여전히 루프가 다 끝난 뒤**라, 고치려던 부모 레벨 C7 위반이 그대로 남는다.
|
||||
구조만 복잡해지고 목적은 못 이룬다.
|
||||
|
||||
**그래서 실질적 선택지는 둘뿐이다** — (A) 인터리브 + 자기 교정(현행),
|
||||
(B) 분해 + 일괄. "인터리브하면서 최종값도 아는" 제3의 안은 구조적으로 없다.
|
||||
|
||||
### 7-4. 부수 이득 둘
|
||||
|
||||
1. **Blocker의 목적이 선명해진다** — `mountSlotTree`는 부기를 전혀 안
|
||||
건드리는 순수 walk라 Blocker가 필요 없다. 결과적으로 Blocker가
|
||||
`materializeSlotTree` **하나만** 감싸게 되고, "이건 배치 *등록*을 게이팅하는
|
||||
물건"이라는 정의와 코드 모양이 일치한다(지금은 물리 마운트까지 같이 감싸고
|
||||
있어 이름과 범위가 어긋난다).
|
||||
2. **백엔드가 갈아끼울 seam이 생긴다** — `mountSlotTree`가 "부기는 끝났고
|
||||
붙이기만 하면 되는" 순수 함수라, 일괄 삽입이 유리한 백엔드(웹의
|
||||
`DocumentFragment` 등)가 **이 함수 하나만** 자기 방식으로 바꿔 끼울 수 있다.
|
||||
인터리브 구조에서는 부기 호출 사이사이에 물리 조작이 박혀 있어 불가능하다.
|
||||
|
||||
### 7-5. 판단 갱신 — 약한 추천에서 **추천**으로
|
||||
|
||||
6-5절은 "약하게 추천"이었는데, 위 7-2(관측 정확도)와 사용자가 짚은 **구현
|
||||
실수 위험**을 더하면 근거가 한 단계 올라간다:
|
||||
|
||||
- 안 쪼개면 C1~C7 일곱 제약이 **한 함수 안에서 줄 순서로만** 지켜진다 —
|
||||
`RC-1`/`RC-3`/`RC-4`가 전부 그 줄 순서를 잘못 잡아서 난 버그였다. 분해하면
|
||||
그중 C2/C3/C7이 **함수 경계로 강제**되어 줄 순서 실수로 깨질 수 없게 된다.
|
||||
- 남는 반대 근거는 "확정된 의사코드를 건드린다" 하나인데, 위 위험과 견주면
|
||||
약하다.
|
||||
|
||||
**단 여전히 M6 착수 전까지 시간이 있고, 실제로 짜보며 확정해도 늦지 않다** —
|
||||
지금 확정할 필요는 없다는 판단은 안 바뀐다.
|
||||
|
|
|
|||
Loading…
Reference in a new issue