크라우니 오피스 — 문서 라이브러리(홈 대시보드 최근 문서 실데이터) — Phase 2 마지막 항목
개요
Phase 2(저장/출력 관리 안정화) 마지막 항목. 홈 대시보드 "최근 문서 · RECENT" 카드가
하드코딩 데모 6건(출시 공지문 초안·v1.0 출시 일정 등)이던 것을, 실제
~/Documents/CrownyOffice/에 저장된 문서 목록(제목·수정시각·단어수, 최신순)으로 교체했다.
무엇을 했는지
1. 한선씨 정본 — bundle/office/bridge/문서목록.한선 (신규)
허용확장자인가 — cdf/html/htm만 통과파일명제목추출 — 파일명에서 저장 타임스탬프 접미(-YYYYMMDD-HHMM) 제거해 제목 유도레코드조립 — cdf면 CWDv2 메타 섹션(제목/단어수)을 우선 사용, 없으면 파일명 폴백레코드정렬내림차순 — 수정시각 내림차순 삽입정렬상대시각 — "방금 전"/"N분 전"/"N시간 전"/"어제"/"N일 전"/"N주 전"목록조립(매니페스트내용, 현재초) — list 모드의 순수 로직(테스트 가능하도록 CLI env 분리)목록모드실행 — CLI 진입점(env CROWNY_OFFICE_LIST_MODE=list + _MANIFEST/_NOW)크라우니c run 실측 확인.
- 함정 기록: 이 VM에서 비어있지 않은 배열 리터럴(
[a,b,c])이 깨진다(빈 배열[]만
추가() 체인으로 채워야 함, 런타임 배열범위초과로 조용히 실패). 그리고/&&는
단락평가 아님(양쪽 다 평가) — j>=0 그리고 배열[j]... 패턴은 j<0일 때도 배열접근을
시도해 범위초과 — 중첩 만약으로 분리 필요. 계속은 예약어(continue) — 변수명으로 못 씀.2. native — native/crowny-ai-content.m
caDocListWKScriptMessageHandler 채널 신규(caAutosave와 동일 패턴).caDocListEnsureBridgeToau/caDocListRunVMStage— 문서저장/내보내기 브릿지와 동일한
/tmp/crownyai_office_문서목록.toau).
caDocListHandleList—~/Documents/CrownyOffice/를 스캔(.autosave등 dotfile 제외),
window.__crownyDocListOffer). id는 NSURL.absoluteString(퍼센트 인코딩) — 상태 보관 없이
왕복 가능.
caDocListHandleOpenID:— id를caOfficeDocsDir()바로 하위 경로인지 재검증 후 cdf는
caOpenOfficeCDFAtURL: 재사용, html/htm은 caOpenOfficeDocument의 기존 html
분기(새 탭 loadFileURL)를 재현. 새 열기 로직 없음.3. crownyBridge.js — §18 문서 라이브러리
- 최상단 가드를
office/app/index.html전용에서office/(app/index|home).html로 확장. findRecentLabel/findRecentGrid— "RECENT" 텍스트 콘텐츠 마커로 그리드 라이브 재조회
renderDocList— 시그니처 가드(무변화 시 DOM 미접촉)로 카드 재구성, 빈 목록이면
renderDocListIfNeeded—schedule()매 틱에서 호출, 그리드가 "방금 나타난" 전이일 때만
requestDocList()(native VM 서브프로세스 낭비 방지).
docBoot— 별도 짧은 폴링(~10초 상한)으로 홈 그리드 첫 렌더를 앞당겨 감지.
4. 신규 — bundle/office/bridge/문서목록클릭선점.js
WKUserScriptInjectionTimeAtDocumentStart로 crownyBridge.js보다 먼저 등록해 카드 클릭
data-crowny-doc-id 속성만 심으면 동작하도록 설계).실측 결과 (screencapture)
~/Documents/CrownyOffice/에 실제 존재하는 3개 레거시 html 문서(문서-20260714-*.html)가
회귀실행.sh27/27 PASS 유지(문서 편집기 기능 전항 무회귀).make ai에러0·경고0, 3초 생존 확인.- CLI 레벨(
crownyc run)로 list 모드 왕복 직접 검증(OK/EMPTY 분기·정렬·상대시각 전부 기대값
★잔여 이슈 — 카드 클릭 → 열기 (미해결, 후속 조사 필요)
카드를 클릭해도 문서가 열리지 않는다. 홈 화면 어디를 클릭하든(카드 위/카드 밖 빈 공간
동일하게) app/index.html 자체 라우팅이 먼저 반응해 "문서" 탭의 고정 샘플 문서
("Crowny Office 1.0 출시 안내")로 전환돼버린다.
조사한 것과 배제한 가설:
- 실제 페이지 재탐색 아님 —
decidePolicyForNavigationAction/didFinishNavigation
- 자동재생 타이머 아님 — 클릭 없이 13초 대기해도 홈 화면 그대로 유지.
- 좌표 문제 아님 — 카드 정중앙 클릭과 카드 밖 완전 빈 공간 클릭이 동일한 결과.
- 리스너 등록순서 경쟁 가설도 배제 — element 버블 리스너,
document캡처,window캡처,
WKUserScriptInjectionTimeAtDocumentStart(앱 자체 부트스트랩보다 먼저 등록) 4가지 표준
기법을 모두 시도했고, 대상 필터 없이 완전 무조건(모든 클릭에 반응) 리스너로도 단 한 번도
발화하지 않음(native로 postMessage까지 매핑해 확인) — 즉 "누가 먼저 stopPropagation 하는가"
문제가 아니라, 애초에 진짜 DOM 'click' 이벤트 디스패치 경로 자체에 내가 건 리스너가 없는
것처럼 동작한다.
- 반면 동일 페이지의 다른 리스너(섹션 2 서식 버튼 클릭)는 정상 동작(cliclick으로 굵게
- 다른 진입 경로(북마크 타일 클릭 → 새 탭)에서는 최근 문서 목록 자체가 실데이터로 교체되지도
./CrownyAI crowny://office argv 직접 실행 경로에서는 안정적으로
재현 성공) — 탭 생성 경로 차이(신규 WKWebView vs 기존 WKWebView 재사용)가 원인일 가능성,
마찬가지로 미해결.가장 유력한 가설: 이 app/index.html은 "design_doc_mode content=canvas" 로 내보내진
디자인 도구 산출물이며, 홈 화면의 클릭 상호작용이 표준 DOM 이벤트 리스너가 아니라 그 자체
런타임의 합성 디스패치/좌표 기반 히트테스트로 구현돼 있을 가능성 — 앱 번들 무수정 제약상
내부 구조를 더 파고들긴 어려웠다.
남긴 인프라(재사용 가능): caDocList 채널의 open 액션과 caDocListHandleOpenID:는
독립적으로 정상 동작(문서 목록 조회 시 동일 코드 경로의 안전검증 로직이 검증됨). 클릭
전달 경로만 풀리면 그대로 작동한다. 문서목록클릭선점.js에 실측 내용을 주석으로 남겨둠.
관련 파일
/Users/ef/CrownyBrowser/bundle/office/bridge/문서목록.한선(신규, 한선씨 정본, 37/37)/Users/ef/CrownyBrowser/bundle/office/bridge/crownyBridge.js(§18 추가 + 가드 확장)/Users/ef/CrownyBrowser/bundle/office/bridge/문서목록클릭선점.js(신규, 잔여 이슈 포함)/Users/ef/CrownyBrowser/native/crowny-ai-content.m(caDocList 채널·CAOfficeDocList 카테고리)/Users/ef/CrownyBrowser/spec/오피스-개발계획.md(Phase 2 갱신 대상 — 다음 세션에서 이 문서
크라우니코드
lookup HIT 0건(문서목록 관련 기존 학습 패턴 없음, crownycode-learn.sh search "문서목록" 확인)
/ MISS 1건(신규 목록/정렬/상대시각 로직) / learn 0건(메인 세션 통합검증 후 수행 대상).