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

크라우니 오피스 — 문서 라이브러리(홈 대시보드 최근 문서 실데이터) — 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)
  • 자체시험 37/37 PASS(확장자필터 5·파일명제목폴백 4·메타추출 7·상대시각 7·목록정렬 5·
  • 목록조립(빈목록 포함) 9). 크라우니c run 실측 확인.
    • 함정 기록: 이 VM에서 비어있지 않은 배열 리터럴([a,b,c])이 깨진다(빈 배열 []
    안전 — 항상 추가() 체인으로 채워야 함, 런타임 배열범위초과로 조용히 실패). 그리고/&&는 단락평가 아님(양쪽 다 평가) — j>=0 그리고 배열[j]... 패턴은 j<0일 때도 배열접근을 시도해 범위초과 — 중첩 만약으로 분리 필요. 계속은 예약어(continue) — 변수명으로 못 씀.

    2. native — native/crowny-ai-content.m

    • caDocList WKScriptMessageHandler 채널 신규(caAutosave와 동일 패턴).
    • caDocListEnsureBridgeToau/caDocListRunVMStage — 문서저장/내보내기 브릿지와 동일한
    mtime 4항 자가치유 캐시 관용구, 별도 toau 경로(/tmp/crownyai_office_문서목록.toau).
    • caDocListHandleList~/Documents/CrownyOffice/를 스캔(.autosave 등 dotfile 제외),
    cdf 파일은 원본을 ascii 임시경로에 재기록(NFD 정규화 함정 회피, 기존 관용구 재사용) 후 VM(list 모드) 1회 호출 → 결과를 UTF-8 안전 base64+TextDecoder로 JS에 전달 (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" 텍스트 콘텐츠 마커로 그리드 라이브 재조회
    (기존 섹션 2/4/9/10/11과 동일 관용구, home.html이 클래스 없이 전부 inline style이라 필요).
    • renderDocList — 시그니처 가드(무변화 시 DOM 미접촉)로 카드 재구성, 빈 목록이면
    "아직 문서가 없습니다" 안내로 교체.
    • renderDocListIfNeededschedule() 매 틱에서 호출, 그리드가 "방금 나타난" 전이일 때만
    requestDocList()(native VM 서브프로세스 낭비 방지).
    • docBoot — 별도 짧은 폴링(~10초 상한)으로 홈 그리드 첫 렌더를 앞당겨 감지.

    4. 신규 — bundle/office/bridge/문서목록클릭선점.js

    • WKUserScriptInjectionTimeAtDocumentStart로 crownyBridge.js보다 먼저 등록해 카드 클릭
    선점을 시도하는 별도 스크립트(카드에 data-crowny-doc-id 속성만 심으면 동작하도록 설계).

    실측 결과 (screencapture)

    • ~/Documents/CrownyOffice/에 실제 존재하는 3개 레거시 html 문서(문서-20260714-*.html)가
    홈 대시보드에 정확히 3장의 카드로 렌더됨(하드코딩 6건 완전 교체), 각각 "문서" 타입· "3일 전"(실제 mtime 기준 상대시각) 표시. 최신순 정렬 확인.
    • 회귀실행.sh 27/27 PASS 유지(문서 편집기 기능 전항 무회귀).
    • make ai 에러0·경고0, 3초 생존 확인.
    • CLI 레벨(crownyc run)로 list 모드 왕복 직접 검증(OK/EMPTY 분기·정렬·상대시각 전부 기대값
    일치).

    ★잔여 이슈 — 카드 클릭 → 열기 (미해결, 후속 조사 필요)

    카드를 클릭해도 문서가 열리지 않는다. 홈 화면 어디를 클릭하든(카드 위/카드 밖 빈 공간 동일하게) app/index.html 자체 라우팅이 먼저 반응해 "문서" 탭의 고정 샘플 문서 ("Crowny Office 1.0 출시 안내")로 전환돼버린다.

    조사한 것과 배제한 가설:

    • 실제 페이지 재탐색 아님decidePolicyForNavigationAction/didFinishNavigation
    네이티브 로그로 클릭 전후 비교, 추가 네비게이션 이벤트 0건 확인.
    • 자동재생 타이머 아님 — 클릭 없이 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건(메인 세션 통합검증 후 수행 대상).