1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# Pure 011: 입력에서 출력까지, 중간 장면 객체 제거
작성일: 2026-09-23. 실제 작성 도구의 호스트·출력 경로 변경과 브라우저 검증.
후속 [012](012-refresh-ownership.md)에서 남은 비용을 프로파일하고 실행 입력과 편집기 갱신의
연결을 제거했다. 아래 수치는 이 보고서 시점의 구현 결과로 유지한다.
## 알아낸 것과 사용 경험
입력마다 전체 장면 스냅샷과 DOM 요소를 다시 만드는 경로를 제거했다.
계산 결과를 기존 출력 요소에 직접 전달하고 값이 달라진 속성·텍스트만 쓴다.
사용자가 코드를 적용하고 키보드·화면 버튼으로 동작시키는 기존 작성 흐름에 연결했다.
별도의 고정 동작 데모를 만들지 않았다. 작성 중인 코드와 적용된 작업의 구분도 유지한다.
**중간 표현과 요소 재생성을 없앤 것은 확인했다. 속도 향상이나 전체 RAM 절감은 입증하지 못했다.**
이번 계측에서 새 경로의 시간 중앙값은 오히려 더 컸고, 표본 간 편차도 컸다.
이를 새 범용 아키텍처나 학술적인 신규성으로 주장하지 않는다.
직접 확인할 동작은 자신이 작성한 값·도형을 입력으로 바꾸고, 정의를 수정하거나 초기화하는 것이다.
입력 갱신 중 같은 SVG 요소를 유지한다. 실제 정의 변경 시에는 출력 구조를 다시 만들 수 있다.
표시 오류가 발생하면 해당 출력을 숨기고, 복구되면 같은 요소를 다시 표시한다.
전체 표시 계산 한도 초과에서는 모든 출력을 숨기되 성공한 입력의 상태는 유지한다.
## 제거한 것과 남긴 것
이전 경로:
입력 → Wasm 상태 변경 → 전체 상태·장면 JS 객체 → 새 DOM 요소 → 전체 교체
현재 경로:
입력 → Wasm 상태 변경 → 표시 계산 검증 → 기존 DOM 목적지에 값 전달
`runtime.present(target)`은 상태 맵·장면 객체를 만들지 않는다.
`output.mjs`는 코드 적용 시 선언과 실제 DOM 목적지를 연결하고, 값은 DOM과 비교한다.
독립적인 숫자 상태 복사본이나 가상 장면 트리를 추가하지 않았다.
DOM은 출력을 보관하며 동작을 결정하는 상태는 여전히 Wasm 안에 있다.
저장·CLI·검사용 `snapshot()`은 명시적으로 호출할 때 유지한다.
작업 한도가 중간에 끝나도 일부 결과만 내보내지 않기 위해 숫자 결과 96개와 유효 표시 24개를
담는 **792 B의 호스트 버퍼**를 재사용한다. typed array 객체 오버헤드, 적용 시 만드는 binding
참조 배열, DOM 목적지 참조는 별도 추가 공간이다. 이 비용을 Wasm 메모리 수치 안에 숨기지 않는다.
무효한 출력도 DOM 요소를 보관하므로 전부 제거하는 이전 경로보다 해당 상황의 유지량이 늘 수 있다.
기존 계산 순서·작업량 제한은 유지한다. 매 갱신의 전체 바인딩 평가, 진단 객체 생성,
편집기 부가 정보 갱신까지 없앤 것은 아니다. ‘모든 할당 0’이나 ‘변경 크기에 비례하는 실행’은 아니다.
출력 콜백 중 실행기 재진입은 거절하며, 출력 어댑터는 신뢰된 동기 코드다.
임의 어댑터 예외의 외부 효과까지 원자적으로 되돌리지는 않는다.
## 실제 브라우저 비교
이전 app/runtime 소스를 보존하고, 테스트 세션의 응답만 바꿔 같은 페이지·Wasm·컴파일러에서 비교했다.
24개 출력과 상태 2개를 사용했다. 이동 입력은 x를 0.25 늘리고, 도형 위치와 텍스트 하나만 바꾼다.
각 실행에서 준비 입력 20회 뒤 입력 100회(누름·해제 200사건)를 처리했다.
이전/현재를 번갈아 각각 3회 실행했으며 모든 최종 상태·출력이 일치했다.
| 관찰 항목, 입력 100회당 | 이전 | 현재 |
|---|---:|---:|
| DOM 요소 생성 호출 | 9,200 | **0** |
| 전체 snapshot 호출 | 200 | **0** |
| 장면 전체 교체 | 200 | **0** |
| 기존 장면 요소의 동일성 유지 | 아니오 | 예 |
| 동기 실행 시간 중앙값 | 648.7 ms | 733.1 ms |
| 동기 실행 시간 범위 | 633.6–941.2 ms | 579.1–751.4 ms |
현재 장면의 변경은 위치 속성 100회와 값 텍스트 100회였다. 텍스트 노드의 교체까지
없어진 것은 아니다. 상태 표시와 비용 표시도 요소를 유지하지만 변경된 텍스트는 갱신한다.
시간은 **브라우저 안의 합성 키보드 dispatch 시작부터 DOM 제출까지**이며 계측 비용을 포함한다.
OS 입력 도착·레이아웃·페인트·실제 화면 표시 시간은 포함하지 않는다.
실제 키보드·포인터 흐름은 별도의 브라우저 조작 검사로 확인했다.
세 표본에서 성능 우위를 주장할 수 없다. 유리한 수치를 얻기 위해 반복 측정을 늘리지 않았다.
app/runtime/output의 비압축 소스 합은 29,334 → 32,558 B로 **3,224 B 증가**했다.
Wasm 파일 53,952 B, 코어 구조 19,128 B, 선형 메모리 65,536 B는 변경하지 않았다.
호스트 heap·브라우저 전체 RSS·GC 시간·GPU 비용의 절감은 측정하지 않았다.
## 검증과 재현
JS/CLI/Wasm 검사 52개가 통과했다. 새 검사에는 보존한 이전 실행기와 결과·계산량 비교,
0~80 작업 한도, 표시 오류, 이벤트 롤백, 부호 있는 0, 정의 교체, 재진입 거절과 어댑터 예외 복구가 있다.
Zig 소스·Wasm은 변경하지 않았으므로 이전 네이티브 검사를 다시 실행한 것으로 세지 않는다.
브라우저에서는 새 경로 비교 13개, 기존 작성 흐름 44개, 표시 한도·복구 12개를 확인했다.
후자의 한도 초과는 테스트 전용 모듈 응답에서 한도를 1로 바꿔 유도한다.
검사 후 원래 설정과 빈 작업물로 복원한다. 이전 증거의 이미지는 덮어쓰지 않았다.
- [변경 전 소스 목록과 해시](../../prototypes/workbench/results/2026-09-23-presentation/before/manifest.json)
- [검사와 현재 소스 해시](../../prototypes/workbench/results/2026-09-23-presentation/verification.json)
- [브라우저 비교 원자료](../../prototypes/workbench/results/2026-09-23-presentation/browser.json)
- [작성 흐름](../../prototypes/workbench/results/2026-09-23-presentation/browser-authoring.json),
[표시 한도](../../prototypes/workbench/results/2026-09-23-presentation/browser-limit.json)
- [실행 계약](../../prototypes/workbench/CONTRACT.md), [재실행 방법](../../prototypes/workbench/README.md)
- [직접 출력 구현](../../prototypes/workbench/web/output.mjs), [실행기](../../prototypes/workbench/web/runtime.mjs)
## 다음 결정
출력 요소 유지와 스냅샷 경로 분리는 실제 작성 도구에 남긴다. 구조 제거의 효과를 관찰할 수 있는
첫 구현이며, 속도·메모리 효율 가설의 합격 판정은 보류한다. 아직 일반 SDK로 고정하지 않는다.
이 결과만으로 데이터 규모를 키우거나 새 캐시·ABI를 추가하지 않는다.
다음 변경의 근거는 현재 경로의 남은 비용과 더 풍부한 직접 조작의 요구여야 한다.
사용자가 대상·관계를 직접 조작하는 기능과 여러 출력 방식의 의미 보존은 이후 작업으로 남아 있다.
|