← 목록
기타 2026-07-12 6KB 읽기 7분

벡터 직결 10ms 파이프라인 — B. ObjC 벡터렌더러 + 라우팅 단일화 완료

개요

CrownyDoc 2026-07-12-벡터직결-계약.md(SSOT)의 "B. ObjC" 절 5개 항목을 /Users/ef/CrownyBrowser/native/crowny-browser.m (단독 소유 파일) 하나에 구현. Makefile 변경 없음(신규 소스 파일 추가 안 함).

무엇을 했는지

  1. CIF v4 글리프 캐시CBGlyphV4(비공개 ivar 클래스, cgPath/em/advance) +
cbParseCIFv4()(M/L/Q/C/Z → CGPath) + cbLoadGlyphV4()(코드포인트→캐시, 딕셔너리, 앱 수명) + cbDrawVectorText()(NFC 정규화 후 문자별 advance×(size/EM) x-전진, 베이스라인=상단+0.8×size — crownyc.c fb_fill_glyph_v4(opcode807) 규약과 동일). 미존재 글리프는 박스 플레이스홀더(블로킹 생성 없음).
  1. display list 렌더 경로CrownyAppView 클래스 익스텐션에
_displayList[CB_VEC_MAX_CMDS]/_displayCount/_vecCanvasW/H/ _hasDisplayList 추가. parseVectorCmd:(INIT/RECT/ROUND/SHADOW/TEXT/HIT/END 파싱, INIT 못 찾으면 실패로 판정해 자동 폴백), drawVectorDisplayList(CTM 한 번 세팅 후 CG로 순회 드로우: RECT=FillRect, ROUND=CGPathCreateWithRoundedRect, SHADOW=CGContextSetShadowWithColor, TEXT=cbDrawVectorText, HIT=그리지 않음). drawRect:_hasDisplayList면 PPM(self.rep) 블릿 대신 이 경로 사용.
  1. termSrv → appSrv 일반화 — 기존 터미널 전용 상주 VM 세션 골격(구
termSrv*/gTermSrv*/kTermSrv*)을 서비스 무관으로 전면 리네임: kAppSrvSrc()src/앱상주서버.한선, kAppSrvToau/tmp/앱상주서버.toau, appSrvStart/Stop/Request/EnsureToauFresh/FindFreePort, 수명주기 판정을 cbIsVectorService(터미널·계산기) 기준으로 확장(appSrvUpdateForTabChange). 4항 stale mtime 가드 유지. CROWNY_TERMSRV_PORT env 이름은 하위호환을 위해 그대로 유지(A 서버가 실제로 이 이름을 읽음, 실측 확인). 신규 appSrvRequestMulti() — 다중행 CMD 응답 전용 소켓 리더(단일행 appSrvRequest와 별개). 중요 버그 실측·수정: A 서버 응답 와이어가 ...END\n\n(본문 자체 trailing \n + TCP쓰기의 +\n으로 개행 2개)로 끝나 naive hasSuffix:@"END\n" 매칭이 항상 실패 → 매 요청 500ms 타임아웃까지 블록되는 치명 함정이었음. trim 후 hasSuffix:@"END"/hasPrefix:@"오류:"로 교정, 실물 서버(포트 19801 수동기동) 대상 왕복 실측 1.6~3.3ms로 확인 후 수정.
  1. 이벤트→벡터 verb 전송injectKey:(KEY/BS), viewDidMoveToWindow
(FOCUS), renderAndReload(렌더, cbIsVectorService면 최상단에서 동기 소켓왕복 시도 후 성공시 즉시 return — 기존 dispatch_async 스폰 파이프라인 완전 우회), mouseDown:(HIT 배열 역순 스캔→매치 시 "액션" 전송) 5곳 모두 "벡터 우선 + 실패 시 기존 스폰/폴백 경로로 자연 낙하" 패턴(sendVectorEvent:arg: 단일 헬퍼로 통일 — 성공 시 표시리스트 갱신+setNeedsDisplay까지 완료). mouseDown:의 rw/rh 계산도 벡터 모드일 때 _vecCanvasW/H 사용하도록 수정 (기존엔 self.rep 기준이라 벡터 모드에서 배율 오판정 함정이 있었음).
  1. 라우팅 단일화 — 신규 routeCrownyAppURL: 메서드로 createTabWithURL
(기존 2026-07-12 "전용 GUI 전면 중단" 무조건 리다이렉트)과 navigateActiveTabTo(기존엔 필터 없이 loadNativeAppURL 직행 — 두 진입점이 서로 다른 판정을 하던 "대충 연결" 버그)를 단일 판정으로 통합. 벡터 지원 서비스(터미널·계산기)만 네이티브 탭 부활, 그 외는 여전히 웹 리다이렉트. 결정기록 주석 삽입.
  1. --selftest-vector [cmd파일경로] CLI 진입점 추가(GUI 불요) — 실물
/tmp/계산기.cmd//tmp/터미널.cmd(A 서버가 실제로 만든 파일)에 parseVectorCmd:를 그대로 돌려 verb 카운트를 로그(오프라인 파서 단위검증).

검증 (실행+출력 근거)

  • clang -fsyntax-only -DCROWNY_VM_WEBKIT -DCROWNY_HYBRID crowny-browser.m
경고 2건(전부 기존 미사용 함수, 내 변경과 무관), 에러 0.
  • clang -fsyntax-only -DCROWNY_PRODUCT_CROWNY crowny-browser.m → 경고 6건
(역시 기존 무관 함수), 에러 0.
  • 두 구성 모두 실제 링크 빌드(Makefile 동일 플래그, 산출물은 스크래치패드에만 —
라이브 배치 안 함) exit 0. otool -L로 crownyonly 변종 WebKit 링크 0 확인.
  • --selftest-vector /tmp/계산기.cmd → PASS (INIT=1 RECT=1 ROUND=17 SHADOW=17
TEXT=18 HIT=16 END=1, 합계69 — A 서버가 만든 실물 파일, HIT verb 포함). /tmp/터미널.cmd도 PASS(21 verb, HIT=3).
  • --selftest-inputv2(기존 회귀 스위트) 19/19 PASS — 회귀 0.
  • A 서버(src/앱상주서버.한선/tmp/앱상주서버.toau)를 포트 19801에 수동
기동해 C/한선씨 두 독립 하네스로 실물 소켓 왕복 실측: 계산기 1.6~2.2ms, 터미널 3.1~3.4ms, 미지서비스 폴백 0.5ms — 전부 done=1(정상 종료판정), 10ms 목표 내. 테스트 종료 후 프로세스 정리(고아 없음).

관련 파일

  • /Users/ef/CrownyBrowser/native/crowny-browser.m (유일 수정 파일, 8071줄)
  • SSOT: 2026-07-12-벡터직결-계약.md(스크래치패드), 가드레일:
~/.claude/templates/한선씨-가드레일.md
  • 검증 스크립트(임시, 스크래치패드): 벡터프로토콜_수동검증.c +
동반 .한선(crownycode-learn 등재: intent=벡터소켓다중행응답대기)

잔여 이슈

  • 조합(한글 자모, injectJamo) 경로는 이번 벡터 직결 배선에서 제외(계약
프로토콜에 명시 안 됨) — 기존 스폰 경로 그대로 유지, 회귀 없음.
  • 터미널 스크롤백 클릭(appAnyHitRect 기반 "빈 영역 판정")은 여전히 구
/tmp/히트맵.psv 파일에 의존 — 벡터 전용 경로로만 구동될 때 이 파일이 갱신 안 되면 스크롤백/버튼 클릭 판정이 약간 부정확할 수 있음(크래시/기능 마비 아님, 근사 동작). C(통합) 단계에서 실사용 시나리오로 재확인 권장.
  • SHADOW 렌더는 CGContextSetShadowWithColor 근사(정확한 blur 반경 시각 대조는
C단계 스크린샷 검증 필요).