# 016 — 대상마다 복제하던 포인터 연결 제거 2026-09-23. 앞 단계는 규칙 본문을 공유했지만, 세 도형의 드래그를 위해 입력 세 개와 반응 연결 열두 개를 따로 만들었다. 이번에는 **입력 하나와 반응 네 개에 대상 표를 연결**한다. 현재 잡은 도형의 상태 구간을 규칙에 전달하고, 접촉 소유권은 도형별로 유지한다. ## 작성과 사용 ```text input drag = pointer { green_box: green blue_box: blue amber_box: amber } on drag.down use grab(drag.target) on drag.move use move(drag.target) on drag.up use drop(drag.target) on drag.cancel use cancel(drag.target) ``` 작업 화면을 새로고침하고 **입력 묶어서 배치 → 예제 불러오기 → 코드 적용**을 누른다. [전체 작성물](../../prototypes/workbench/examples/routed-layout.pure)은 이전과 같은 잡은 위치 유지, 경계 제한, 놓기 확정, 취소 복귀, 선택한 도형의 방향키 조정을 제공한다. 한 그룹 안의 도형 두 개를 동시에 움직일 수 있다. 하나를 놓거나 취소해도 다른 도형의 소유권은 유지되며, 이미 놓은 도형은 다른 접촉을 취소해도 되돌아가지 않는다. 같은 record 타입의 item끼리 묶는다. 도형과 대상의 연결은 명시하지만 네 반응은 대상마다 작성하거나 컴파일해 복제하지 않는다. 마지막 입력 표시에는 대상 도형도 나온다. CLI는 `point-target drag green_box move 210 220`으로 같은 경로를 실행한다. ## 실제 실행 표현 컴파일러는 도형 이름을 item의 연속 필드 구간에 연결한다. VM에 저장되는 대상 하나는 `input, base, count` 세 바이트다. 그룹 반응의 메타데이터에는 ‘이번 사건의 대상’을 사용한다는 표시와 필드 수만 둔다. 명령 본문과 연결 수는 도형 수만큼 늘어나지 않는다. 브라우저는 처음 잡은 도형을 캡처 기록에 유지한다. 런타임은 코드 적용 시 만든 이름 조회 표로 대상 번호를 찾고, VM은 그 번호로 활성 대상 표를 직접 읽는다. 포인터가 움직일 때마다 그룹의 모든 도형을 검색하거나 각 도형의 규칙을 실행하지 않는다. 기존의 제한된 핸들러 목록에서 사건 번호를 비교하는 순회는 남아 있다. 소유권 키는 입력 이름과 도형 이름의 조합이다. 같은 도형의 두 번째 접촉은 소유권을 가져갈 수 없다. `releaseAll`은 잡고 있는 도형 각각에 취소를 한 번씩 보낸다. 그룹끼리 같은 item을 중복 연결하는 것도 거절해 필드 구간이 겹치는 캡처를 막는다. 작성자가 다른 전역 상태나 명시적 대상에 쓰는 일반 반응까지 금지하는 정책은 아니다. VM은 잘못된 대상 번호, 다른 입력의 대상, 누락된 대상, 범위를 벗어난 필드를 거절한다. 하나의 사건에서 앞의 반응이 쓴 값도 뒤의 반응이 실패하면 함께 취소한다. 준비 중인 연결 표는 활성 표를 바꾸지 않는다. 소스 적용과 파일 복원은 입력을 모두 놓은 뒤에만 가능하고, 이름을 기준으로 표를 다시 만든다. 파일에는 물리 대상 번호를 저장하지 않는다. ## 확인한 비용과 한계 동일한 최종 코어에 두 작성물을 넣은 저장 구조 회계다. 속도 벤치마크는 하지 않았다. | 항목 | 공유 규칙 + 대상별 입력 | 공유 규칙 + 그룹 입력 | |---|---:|---:| | 전체 입력 | 7 | 5 | | 포인터 반응 연결 | 12 | 4 | | 전체 반응 연결 | 24 | 16 | | 저장 명령 | 117 | 117 | | 대상 표 | 0 B | 9 B | | 사용 중인 명령·연결·대상 표 | 2,256 B | 2,137 B | | 숫자 상태 | 25 | 25 | 대상 표 24칸을 예약하면서 활성/준비 프로그램에 각각 80 B가 추가됐다. 코어 고정 예약은 **19,904 → 20,064 B**, Wasm 선형 메모리는 64 KiB로 유지된다. 현재 예제의 사용 자료는 줄었지만, 고정 예약은 늘었다. JS의 조회 Map과 메타데이터, 브라우저 전체 메모리는 이 수치에 포함하지 않는다. 전체 메모리나 실행 속도의 우위로 해석하지 않는다. [구조 회계](../../prototypes/workbench/results/2026-09-23-pointer-routing/representation.json). 1·3·9·24개의 작은 대상을 컴파일해 하나의 입력과 하나의 이동 반응이 유지되는지도 검사했다. 이는 기존 입력 8개 한도와 대상 수를 분리했는지 확인하는 경계 검사다. 큰 앱이나 많은 도형의 성능 실험으로 세지 않는다. 총 상태 32개, 출력 24개 등의 기존 한도는 그대로이며, 현재 Tile의 8필드 구성으로 24개 도형을 만들 수 있다는 뜻도 아니다. ## 검증과 남은 작업 코어 검사 35개와 Node/CLI 검사 83개가 통과했다. 기존 배치와 동일한 입력을 전달해 모든 필드와 출력을 비교했고, 동시 접촉·일부 취소·소유권 침범 거절·그룹 혼동 거절· 실패 원자성·표시 캐시 갱신·선언 순서 변경·제거 후 재선언·파일 복원을 확인했다. 그룹 예제의 브라우저 확인 30개, 기존 작성 흐름 44개, 이전 대상별 포인터 흐름 23개도 통과했다. 브라우저에서는 실제 마우스와 Chromium CDP 터치로 조작한다. 개별 접촉 종료 검사에서 처음에 남겨둘 접촉을 종료하도록 보낸 오류를 바로잡았다. 기록된 실제 `pointerup`과 남은 소유권을 함께 확인했다. 이동 검사는 CDP 명령 응답 이후 실제 사건이 반영될 때까지 기다린다. 이 재현은 실제 모바일 하드웨어 검증을 대신하지 않는다. [검증 자료와 재현](../../prototypes/workbench/results/2026-09-23-pointer-routing/README.md). 이 결과는 입력마다 대상을 별도 연결하던 비용을 분리한 구현이다. 독창적인 새 프로그래밍 개념이나 대규모 서비스 최적화의 증거로 제시하지 않는다. 다음 문제는 **선택 대상의 식별과 키 입력의 직접 전달**이다. 현재 예제의 `selected`와 `id`는 작성한 숫자 상태이며, 방향키는 여전히 대상별 조건을 검사한다. 이를 해결할 때는 선택 없음, 선택 대상 제거, 저장 복원 뒤 선택, 잡고 있는 대상과 선택이 다를 때의 정책을 먼저 고정해야 한다. 동적 생성·삭제에는 오래된 입력이 재사용된 슬롯으로 전달되지 않는 수명 식별도 필요하다. 이번 대상 번호는 정적 정의 안의 주소이며 그 역할을 대신하지 않는다.