← 목록
기타 2026-07-14 7KB 읽기 8분

크라우니 오피스 브릿지 1차 실증 (punch #1 서식 + #2 상태바)

개요

spec/오피스-개발계획.md "두뇌 연결 = 한선씨 엔진 브릿지"의 [즉시층] 첫 구현. spec/문서기능-판정표.md에서 실측된 punch #1(B/I/U/S가 버튼 자기 하이라이트만 토글, 선택 텍스트에 미적용)과 punch #2(상태바 단어/글자수가 하드코딩 리터럴)를 앱 번들(bundle/office/app/index.html) 무수정으로 해결. 셸이 WKUserScript로 순수 JS(crownyBridge.js)를 주입해, 앱의 죽은 껍데기(div onClick 자기 하이라이트, 하드코딩 statusMap) 위에 실제 로직을 얹는 방식.

무엇을 했는지

D1 — crownyBridge.js (신규)

  • 위치: bundle/office/bridge/crownyBridge.js
  • 가드: location.pathnameoffice/app/index.html을 포함하지 않으면 즉시 종료(공유 WKUserContentController가 전 탭에 스크립트를 주입하므로 자체 가드 필수).
  • 서식: mousedown capture에서 B/I/U/S 버튼(span.sc-interp 텍스트 + 부모 div의 인라인 style 힌트로 식별, font-weight/font-style/text-decoration) 클릭 시 preventDefault로 선택영역 보존 → click capture에서 document.execCommand('bold'/'italic'/'underline'/'strikeThrough')로 실제 적용. 앱 자체의 onClick(자기 하이라이트)은 막지 않고 그대로 유지, 이후 queryCommandState로 버튼 활성상태를 실제 커서 위치 서식과 재동기화(syncFormatButtons).
  • 상태바: input/selectionchange/MutationObserver(재렌더 방어) 트리거로 computeStats() — 단어수(공백류 [ \t\n\r]+ 분리 토큰, 한글은 어절 단위)·글자수(공백류 제외) 재계산 → "N단어"/"N자" 숫자 패턴을 정규식으로 찾아 상태바 텍스트 노드에 그대로 치환(원문의 "1페이지"/"한국어" 등 나머지는 보존).

D2 — 문서통계.한선 (신규, 정본 동반)

  • 위치: bundle/office/bridge/문서통계.한선
  • JS computeStats()의 한선씨 정본 미러. crowny-word/도구/문서통계확장.한선공백문자인가/단어분리 로직을 이 파일 안에 이식(원본 미수정, 기존 학습패턴 fn_문서통계확장_공백문자인가/fn_문서통계확장_단어분리 재사용).
  • 공개 함수: 단어수(텍스트), 글자수공백제외(텍스트).
  • 자체시험 10건(5개 케이스 × 2함수) — JS computeStats()와 동일 입력으로 수기 교차계산 후 값 일치 확인.

D3 — 셸 배선

  • native/crowny-ai-content.m: caOfficeBridgeScriptSource() 헬퍼 추가(번들 리소스 office/bridge/crownyBridge.jsCROWNY_BROWSER_ROOT/bundle/office/bridge/crownyBridge.js 2단 폴백, 기존 caiAssetPath 규약과 동일 패턴). CrownyContentView init에서 _ucc(공유 WKUserContentController) 생성 직후 WKUserScript(injectionTime:AtDocumentEnd, forMainFrameOnly:YES)로 addUserScript.
  • native/배포패키징.sh: Contents/Resources/office/bridge/ 복사 라인 추가(office/app과 동일 패턴).
  • crowny-browser.m, crowny-shell.m, Makefile 기존 타깃, 앱 번들(bundle/office/app/)은 무수정.

게이트 결과

  1. hanseonc_high 컴파일 + crownyc run: ./hanseonc_high 문서통계.한선 > x.toau && ./crownyc run x.toauPASS 10/10.
  2. make ai: cc -O2 -Wall ... 경고 0·에러 0, strip -x 완료(409K). ./CrownyAI 백그라운드 실행 후 3.5초 뒤 프로세스 생존 확인, 크래시 로그 없음. cc -fsyntax-only -fobjc-arc -DCROWNY_HYBRID crowny-ai-content.m 클린.
  3. 실측(CDP, Chrome :9333, 셸 없이 로직 검증)file:///Users/ef/crownybrowser/bundle/office/app/index.html에 이미 로드된 세션에 crownyBridge.jsRuntime.evaluate로 그대로 주입(node 워크어라운드로 파일 내용을 직접 전송, 셸따옴표 문제 회피) 후:
- 서식 before/after: 텍스트 "몇 달간의 베타 테스트"(12자) 선택 → B 버튼에 합성 mousedown/mouseup/click 디스패치 → ce.innerHTML.length 3825→3832, <b>/<strong> 개수 1→2, 신규 <b>몇 달간의 베타 테스트</b> 확인(wrapped:true). 지연 후 B 버튼에 data-crowny-active="1" + 하이라이트 인라인 style 확인(커서 위치 실제 서식과 버튼 상태 동기화 확증). - 상태바 before/after: 편집영역 끝에 " TESTWORD12345"(공백포함 14자, 공백제외 13자) execCommand('insertText') 삽입 → ce.innerText.length 428→442(+14, 정확히 일치) → 상태바 텍스트 "1페이지 · 99단어 · 325자 · 한국어" → "1페이지 · 100단어 · 338자 · 한국어"(단어 +1, 글자 +13, 삽입 문자열과 정확히 일치). 하드코딩 리터럴("1,243단어 · 6,812자")이 실제 편집 이전에 이미 실측값(99단어·325자)으로 살아있었음도 확인(초기 boot 폴링 → MutationObserver가 정상 작동 중이라는 방증).
  1. 셸 주입판(WKUserScript 경유 실배선): 이번 세션에서는 미실행(스펙상 "선택"). native/crowny-ai-content.m 문법검사 통과 + 동일 _ucc가 오피스 탭 webview 생성(makeWebView)과 caOpenOfficeInActiveTabloadFileURL 대상 모두에 공유되는 구조를 코드로 확인. 실기 WKWebView는 CDP 원격디버깅 대상이 아니라(Web Inspector 별도 트랙 필요) 이번 실증 범위에서 제외 — 후속 트랙에서 Safari 원격 웹 인스펙터로 재검증 권장.

관련 파일

  • /Users/ef/crownybrowser/bundle/office/bridge/crownyBridge.js (신규)
  • /Users/ef/crownybrowser/bundle/office/bridge/문서통계.한선 (신규, 정본)
  • /Users/ef/crownybrowser/native/crowny-ai-content.m (수정: caOfficeBridgeScriptSource() + _ucc WKUserScript 등록)
  • /Users/ef/crownybrowser/native/배포패키징.sh (수정: bridge/ 복사)
  • 참조: /Users/ef/crownybrowser/spec/오피스-개발계획.md, /Users/ef/crownybrowser/spec/문서기능-판정표.md, /Users/ef/crowny-word/도구/문서통계확장.한선

크라우니코드

  • lookup HIT 1건(문서통계 계열 다수 — fn_문서통계확장_공백문자인가/단어분리 재사용) / MISS 1건(단어수 글자수)
  • learn 1건 등록(문서통계_글자수공백제외), 1건은 코드 길이 미달로 학습기가 무시(문서통계_단어수, 정상 동작에는 무관)

잔여 이슈

  • 실기 WKWebView 경유 실배선 검증(게이트 4)은 미실행 — Safari 원격 웹 인스펙터 또는 WKWebView.isInspectable + CDP 유사 브리지로 후속 검증 권장.
  • 판정표 punch #3~#10(실행취소/재실행, 찾기 실동작, 삽입 3종, 개요 동기화, 댓글 CRUD, 히스토리 스냅샷, 단축키, 드롭다운 3종)은 이번 스코프 밖 — Phase 1-A 후속 착수 순서대로 진행.
  • 상태바 "저장상태"/"페이지 수"/"언어감지"는 이번 스코프(단어/글자수만) 밖, statusMap 문자열의 나머지 구간은 그대로 하드코딩 유지.
  • 서식 동기화(syncFormatButtons)는 클릭 직후 setTimeout(0)에 의존 — 매우 빠른 연속 클릭/재렌더 경쟁 상황에서 드물게 한 프레임 지연 가능(치명적이지 않음, 후속 다듬기 대상).
  • CDP 테스트 하네스 스크립트(cdp_inject_file.js, test_bold.js, test_bold2.js, test_statusbar.js)는 scratchpad 1회성 검증용 — DOM/WebSocket 프로토콜 조작뿐이라 계산 로직이 없어 한선씨 동반을 생략함(기존 win/cdp평가.js도 동일 취급).