← 목록
AI 2026-07-26 5KB 읽기 5분

CrownyAI 런처 — 클로드 디자인 목업 → ObjC 네이티브 drawRect 이식

개요

design_handoff_크라우니앱/런처-{네이티브,웹서비스,오프라인}-{라이트,다크}.html 6개 목업(800×600, 절대좌표)을 crowny-ai-engine.mCrownyAppView 런처 drawRect/mouseDown에 그대로 이식. 색·좌표·문구는 목업에서 복사(재창작 금지), 카드 데이터는 src/앱목록.psv(appListEntries) 실데이터.

무엇을 했는지

  1. src/런처레이아웃.한선(SSOT, 신규) — 목업 800×600 절대좌표를 순수 함수로 이식(헤더/탭바/카드
9칸 그리드/페이지네이션/오프라인 카드). 나눗셈 자연반올림 함정 우회를 위해 _올림분할9(뺄셈 루프) 사용. 자체시험 29/29 PASS(hanseonc_high 컴파일 + crownyc run).
  1. native/crowny-ai-engine.m(런처 구간만):
- cavBasisToView(bounds, x0,y0,w0,h0) — 800×600 기준 좌표 → 뷰 bounds 매핑(비균등 스트레치 sx=뷰W/800, sy=뷰H/600, drawVectorDisplayList와 동일 스케일 정책). 스케일 적용 유일 지점. - caiLogoImage extern 재사용(crowny-ai-chrome.m 정본 왕관 벡터, 재창작 안 함) — 로고 자리에 배치. - drawRect 런처 분기 전면 재작성: 목업 그대로(헤더+새로고침, 탭바+언더라인+구분선, 카드 9칸/쪽(3×3)+학습배지, 페이지네이션, 오프라인 카드). - launcherCardRects: — 9칸 고정 그리드로 재정의(cavBasisToView 기반). - mouseDown 런처 분기 — 로고(홈)/새로고침/탭전환/카드열기/이전·다음 페이지/오프라인 재시도 히트. - 인스턴스 상태 런처탭(0=네이티브,1=웹)·런처페이지네이티브·런처페이지웹 추가(탭당 독립 페이지). - gLauncherWebOffline/gLauncherLastSuccessAt/launcherFetchManifestNow — 학습배지 manifest fetch 성패를 오프라인 신호로 재사용(기존 dispatch_once 1회 캐시를 재시도 가능한 구조로 리팩터). - 미사용 경고 방지: launcherAccentForApp(신규 목업이 액센트 점을 안 씀) __attribute__((unused)).

검증

  • 런처레이아웃.한선: hanseonc_high 컴파일 exit0 → crownyc run "런처레이아웃 검증: 29/29" "[결과] 티 — PASS".
  • make ai: exit0, 신규 경고 0(사전존재 4건 — main.m getter 3 + butler unused-function 1, 회귀 아님).
  • 파리티 대입표(한선 SSOT 출력값 ↔ ObjC cavBasisToView 인자, 발췌):
| 함수(한선) | 반환 | ObjC 호출 | 일치 | |---|---|---|---| | 카드_rect(0) | [24,136,240,108] | cavBasisToView(B,24,136,240,108) | ✓ | | 카드_rect(4) | [280,258,240,108] | row=1,col=1→cx0=280,cy0=258 | ✓ | | 카드_rect(8) | [536,380,240,108] | row=2,col=2→cx0=536,cy0=380 | ✓ | | 로고rect() | [24,20,28,28] | cavBasisToView(B,24,20,28,28) | ✓ | | 탭언더라인_x(웹) | 152 | underlineX=152(webTab) | ✓ | | 페이지네이션_이전버튼() | [236,524,104,40] | prevR=cavBasisToView(B,236,524,104,40) | ✓ | | 오프라인재시도버튼() | [332,336,136,44] | retryR=cavBasisToView(B,332,336,136,44) | ✓ | | 페이지수(10) | 2 | (10+8)/9=2(C truncate=ceil for양수) | ✓ | | 페이지수(17) | 2 | (17+8)/9=2 | ✓ | | 페이지항목범위(1,10) | [9,1] | start=9,count=min(9,1)=1 | ✓ | | 이전활성(0)/다음활성(0,2) | -1/1 | prevActive=NO/nextActive=YES | ✓ |
  • 라이브 앱·9801 서버 무접촉(지시 준수). GUI 육안은 통합 세션 담당(범위 외).

관련 파일

  • /Users/ef/CrownyBrowser/src/런처레이아웃.한선 (신규 SSOT, 29/29 자체시험)
  • /Users/ef/CrownyBrowser/native/crowny-ai-engine.m (런처 구간만 수정, 백업=.bak-런처이식)
  • 원본 목업: /Users/ef/Downloads/design_handoff_크라우니앱/런처-{네이티브,웹서비스,오프라인}-{라이트,다크}.html
  • 이식노트: /Users/ef/.claude/design-port/크라우니앱벡터/이식노트.md (이번 작업 개선 아이디어 없음 — append 안 함)

크라우니코드 학습

~/.claude/scripts/crownycode-learn.sh lookup HIT 0건 / search·lookup MISS 2건(신규 패턴) / learn 추가 1건 (intent=런처_디자인이식_레이아웃SSOT).

잔여 이슈

  • GUI 실측(앱 재시작 후 crowny://app/런처 육안 확인, 라이트/다크·네이티브/웹서비스 탭·페이지네이션·
오프라인 상태)은 통합 세션 담당(이번 작업 지시 범위 밖 — "라이브 앱·9801 서버 무접촉").
  • install-ai-app.sh 미실행(지시에 따라 설치/앱 재시작은 통합 세션 담당) — 반영은 다음 설치+재시작부터.
  • 오프라인 판정은 학습배지 manifest fetch(game.crowny.org) 성패에 결속 — 실제 웹서비스 카드 목록 자체는
로컬 src/앱목록.psv 기반이라 항상 로드됨(오프라인 카드가 뜨는 동안에도 카드 데이터 자체는 유실 아님, 기존 설계 의도인 "배지 소스 단절 신호"를 그대로 재해석).