벡터 직결 10ms 파이프라인 — 담당 C(통합 E2E 검증) 완료
개요
담당 A(한선씨 src/앱상주서버.한선)와 담당 B(ObjC native/crowny-browser.m)의 구현을
/private/tmp/claude-501/-Users-ef/2e95e8b6-e663-4b81-9734-9ded4339b18d/scratchpad/벡터직결-계약.md
"C. 통합 검증" 절에 따라 통합·실측·배포했다. 판정: p50 4.39ms / p95 5.03ms — 목표(10ms 미만) 충족.
무엇을 했는지
- 빌드:
cd /Users/ef/CrownyBrowser/native && make— exit 0, 신규 경고 0(기존 무관 경고 2건만). - 서버 스모크:
src/앱상주서버.한선재컴파일(exit0) → 임시 포트(19802) 1회성 기동 →
벡터|계산기|렌더(73줄 CMD 정상)·벡터|계산기|액션 체인(7+3=10 정확)·
벡터|터미널|FOCUS/KEY/BS(입력상태 정확 반영)·레거시 키|/렌더|/렌더|CW|CH/종료 전부 회귀 0.
상태파일 원복, 포트 해제, 고아 프로세스 0 확인.
- ObjC 계측 추가(통합검증 목적, 가벼운 NSLog 1줄 — B가 이미 만든
sendVectorEvent:arg:/drawRect:에 삽입):
CrownyAppView 클래스 익스텐션에 _vecEvtStartTS(NSTimeInterval)·_vecEvtName ivar 추가.
- sendVectorEvent:arg: 진입 시각 기록 → drawRect:의 drawVectorDisplayList 직후
[CB_VEC_RTT] service=%@ event=%@ ms=%.3f 로그(이벤트 처리 시작→CG 드로우 완료 왕복).
- CACurrentMediaTime()은 QuartzCore 미링크로 링크 에러 발생 → [NSDate timeIntervalSinceReferenceDate]로 대체
(서브ms 해상도, 기존 appSrvRequestMulti와 동일 시각원 — 추가 프레임워크 링크 불요).
- E2E 구동 하네스 추가(테스트 전용, env-gated):
CROWNY_AUTOSEQ=<step>;...(CROWNY_AUTOAPP와 함께 사용) —
click:X,Y(뷰좌표 직접 클릭)/key:<c|BS>(injectKey: 직접 호출)/hit:<액션명>(좌표계산 없이 표시리스트
HIT 항목을 액션명으로 직접 클릭 — mouseDown:의 히트테스트와 동일 로직, 신규 clickHitAction: 헬퍼)
3종 스텝을 90ms 간격 순차 실행. 기존 CROWNY_AUTOCLICK(단일 클릭) 패턴을 그대로 일반화한 것으로,
일반 실행 경로는 env 미설정 시 진입 자체가 없어 무영향.
- 실측(실제 GUI 프로세스, 프로덕션 함수 경유):
hit:숫자:7~hit:등호): 액션 이벤트 10개 전부 성공, 2.735~3.993ms.
- 터미널 키 20회(h,e,l,l,o,BS,o,_,w,o,r,l,d,BS,d,1,2,3,BS,9): KEY/BS 20개 전부 성공, 3.819~5.372ms.
- 합산 30샘플: p50=4.39ms, p95=5.03ms, max=5.37ms — 전부 소켓왕복+파싱+CG드로우 완료까지 포함.
- --selftest-inputv2(19/19 PASS)·--selftest-vector(PASS) 재실행 — C의 계측/하네스 추가 후에도 회귀 0.
- 회귀 확인:
CROWNY_STARTURL=https://crowny.org 6초 구동, 크래시 없음.
- 콜드스폰 폴백: 상주서버 후보 포트 9801~9820(20개)을 nc -l로 전부 점유해 상주서버 기동 실패를 유도 →
[CB_VEC_RTT] 로그 0건(벡터 경로 미시도 확인) + /tmp/계산기.ppm mtime 갱신(레거시 스폰 경로 정상 동작,
계산기렌더.sh 그대로 재생성) 확인. 테스트 후 포트 전부 해제.
- 미전환 앱(메모): CROWNY_AUTOAPP=메모 구동 — [CB_VEC_RTT] 0건(벡터 비대상 서비스, PPM 경로 그대로),
정상 캡처.
- 시각 확인:
/tmp/점검_e2e_계산기_seq.png(4x4 버튼그리드+디스플레이 "0", 벡터 CG 렌더 크리스프 폰트),
/tmp/점검_e2e_터미널_seq.png(스크롤백 $ ls 출력 + 입력칸에 20키 결과 정확 반영) — 둘 다 로그상
"앱뷰(네이티브) 캐시 PNG"(벡터 표시리스트 경로) 캡처로 확인, PPM 블릿 경로가 아님을 로그로 구분.
- 배포: 판정 통과 확인 후 3곳에 안전 배치 —
cp로 같은 디렉토리에 스테이징 파일(*.new) 생성 후
mv로 최종 경로에 원자적 교체(대상 파일 직접 cp 덮어쓰기 금지 — 서명캐시 SIGKILL 함정 회피).
native/CrownyBrowser / CrownyBrowser.app/Contents/MacOS/CrownyBrowser /
CrownyAI.app/Contents/MacOS/CrownyBrowser 3곳 sha256 전부 일치
(99c4a0908cacb97b984bb4beefc38c8b9d74ca538e5375ccef82ad6fc05a2638). 실행 중 앱 재시작은 하지 않음
(작업 시작 시점부터 CrownyAI.app/CrownyBrowser 프로세스 자체가 미기동 상태였음, pgrep 확인).자체 발견·정정한 실수
- 폴백 테스트 준비 중
rm -f /tmp/계산기.ppm으로 기존 공유 캐시 파일을 삭제(가드레일 "기존 /tmp 캐시(.ppm)
계산기렌더.sh를 직접 실행해 정상 산출물로 재생성, 이후 재검증은 삭제 없이
mtime 비교로만 진행해 재발 방지.관련 파일 경로
/Users/ef/CrownyBrowser/native/crowny-browser.m— C가 추가한 계측(§sendVectorEvent/drawRect) +
runAutoSeq:/clickHitAction:), B의 기존 구현 위에 얹음(구조 변경 없음).
/Users/ef/CrownyBrowser/native/CrownyBrowser,CrownyBrowser.app/…,CrownyAI.app/…— 배포된 3 바이너리./tmp/점검_e2e_계산기_seq.png,/tmp/점검_e2e_터미널_seq.png— 시각 확인 스크린샷./tmp/e2e_calc_hit.log,/tmp/e2e_term_keys.log,/tmp/e2e_fallback3.log— 실측 로그 원본.
잔여 이슈
- p50/p95는 "이벤트 핸들러 진입→CG 드로우 완료"까지만 측정(OS 이벤트 디스패치·실제 화면 vsync 합성은
- B가 이미 명시한 잔여 범위(자모 IME 미포함, 터미널 스크롤백 히트맵 구파일 의존, SHADOW 시각 대조 미실시)는
CROWNY_AUTOSEQ/clickHitAction:은 테스트 전용 하네스로 코드에 남겨둠(계약 "임시 NSLog 추가 후 유지"
clickHitAction:은 외부 미호출).