b3os-mac-app-shell · git:20260726.20a4aa2 · 2026-07-26 · sha256 f0f6471a41a9921b

b3os-mac-app-shell git:20260726.20a4aa2A

Immutable. This exact content is served forever at /api/v1/blob/f0f6471a41a9921b.

---
name: b3os-mac-app-shell
description: 웹 대시보드/웹앱을 Apple 네이티브 셸(.app)로 빠르게 래핑하는 팀 스킬. mac-iphone-shell 골격(SwiftUI multi-platform + WKWebView 라이브러리 + HostApp 패턴)을 참조해 URL 구성형 Mac/iPhone 앱을 만들고 .app으로 패키징한다. "이 웹대시보드를 맥앱으로 만들어줘", "b3os.app 같은 셸 앱", "사내 웹툴 네이티브 래핑"일 때 사용. 검증된 함정(특히 WebView 창 채움/viewport)을 피하는 레시피 포함. 주 사용자·업데이트 책임자: agent A·developer.
---

# b3os-mac-app-shell

웹앱을 Apple 네이티브 셸(.app)로 래핑하는 팀 표준 레시피. **별도 골격 저장소를 참조**하며 코드를 복제하지 않는다 — 이 스킬은 "언제·어떻게·무엇을 조심"의 운영 지식이고, 실제 구현·빌드 스크립트는 골격에 있다.

> ★선행 조건 — 골격 저장소는 이 저장소에 들어있지 않다.★
> 정본 골격은 **b3rys 내부 비공개 저장소 `mac-iphone-shell`**(SwiftUI multi-platform 라이브러리 + HostApp 패턴)이다. 접근 권한이 있는 팀원이 따로 clone해야 하고, 아래 절차와 references의 경로는 **본인이 clone한 위치**를 가리킨다(이 문서에서는 `$SHELL_SKELETON`으로 쓴다).
> 접근 권한이 없으면 이 스킬의 빌드 절차는 실행할 수 없다 — "검증된 함정"·"검증 절차" 절의 운영 지식만 참고 자료로 쓴다.
>
> owner / 업데이트 책임자: **agent A, developer** (둘이 함께 유지·리뷰)

## 언제 쓰는가

- 이미 있는 웹 대시보드/웹툴을 **설치 가능한 Mac 앱(.app)** 으로 내보내고 싶을 때 (예: b3os 대시보드 → `b3os.app`)
- "맥앱으로 래핑한 티 안 나게, 라이트/다크 seamless, 창이 네이티브처럼" 요구
- iPhone 동반 앱(같은 골격, read-only/동일 셸)도 필요할 때
- ❌ 쓰지 않는 경우: 네이티브 UI가 본질인 앱(웹뷰가 아니라 SwiftUI 화면이 주). 그건 골격 없이 일반 SwiftUI로.

## 전제 · 요구사항 (이게 없으면 이 스킬은 못 쓴다)

- **macOS Sonoma 14+** (골격 deployment target). **Xcode 16.2+** (`xcodebuild -version`). Swift toolchain 포함.
- 배포(외부 공개)하려면 **Apple Developer 계정** + Developer ID Application 인증서. 로컬/팀 테스트는 ad-hoc만으로 가능(서명 안 됨).
- 이 스킬은 **macOS 빌드 환경 전용** — Windows/Linux에선 `.app` 빌드 불가(셸 컨셉만 참고).
- 핀(검증된 조합): macOS 14 / Xcode 16.2 / 골격 `mac-iphone-shell` 최신 main. 더 높은 버전은 빌드 후 §검증 통과 시 사용.

## 입력값 (앱마다 정하는 것)

| 값 | 무엇 | 어디서 설정 |
|---|---|---|
| **webURL** | 셸이 로드할 웹 주소 | `AppShellSettings.defaultWebURL` (기본 `http://localhost:7878/team`) + 런타임 UserDefaults 키 `AppShell.webURL`로 덮어쓰기 가능 |
| **app name** | `.app` 표시 이름 | 골격의 `$SHELL_SKELETON/scripts/package-macos-app.sh`의 `APP_NAME` (예: `b3os.app`) / Xcode HostApp 프로젝트명 |
| **product name** | 빌드 산출 바이너리 | 같은 스크립트 `PRODUCT_NAME` (예: `B3rysMacApp`) |
| **bundle id** | 번들 식별자 | Xcode HostApp 프로젝트 (Signing & Capabilities) |
| **WKAppBoundDomains** | 셸이 이동 가능한 도메인 화이트리스트 | HostApp `Info.plist` (보안: `limitsNavigationsToAppBoundDomains=true`와 한 세트) |

## 절차 (요약 — 상세는 골격 저장소의 `docs/QuickStart.md` "30분")

1. 골격 라이브러리 가져오기 — 내부 비공개 저장소를 `$SHELL_SKELETON`으로 clone하거나 SPM 의존성으로 추가
2. Xcode에서 App 프로젝트(HostApp) 생성 → AppShell 라이브러리 추가
3. App entry를 `AppShellRootView`(셸)로 교체, `webURL`·환경 주입
4. `Info.plist`: `WKAppBoundDomains` + 환경 도메인 설정
5. Capabilities (서명용 — Apple Developer 계정)
6. 빌드·실행: `swift build` / Xcode Run
7. 배포용 `.app` 패키징: `$SHELL_SKELETON/scripts/package-macos-app.sh` → `.build/<APP_NAME>` (테스트=ad-hoc 서명, 배포=notarize)

## 산출물

- 더블클릭으로 실행되는 `.app` (테스트: ad-hoc 서명 / 배포: Developer ID 서명 + notarization)
- 라이트/다크 자동 추종, 네이티브 창 chrome(타이틀바 통합·이동·디스플레이 변경 재클램프)
- (선택) iPhone 동반 앱 — 같은 골격 + 플랫폼 분기

## 검증 절차 (반드시)

1. `swift build` 0 에러
2. **창 채움 실측 (회귀 가드)** — 앱 실행 후 webview 높이 == 창 높이인지 *측정으로* 확인. 방법: in-app JS로 `document.documentElement.clientHeight`(또는 `window.innerHeight`)를 네이티브 창 높이와 비교 → 같으면 OK, webview가 더 크면 viewport 부풀림 회귀(아래 회귀주의 3종세트 점검). 화면 못 보는 세션은 측정값을 `/tmp` 로그로 남기고 the team lead/실기 확인 위임.
3. 라이트/다크 전환 seamless(셸 배경이 웹과 어긋나지 않음)
4. 창 리사이즈·디스플레이 변경 시 잘림/벌어짐 없음
5. 배포 전: notarization 통과 + Gatekeeper 통과(`spctl -a`)

## ⚠️ 검증된 함정 — 반드시 references 읽기

- [`references/viewport-and-gotchas.md`](references/viewport-and-gotchas.md) — **WebView 창 채움 버그(위 벌어짐/아래 잘림) 회귀주의**. NonIntrinsicWebView + autoresizing pin 3종세트. 제거 금지.
- [`references/build-sign-notarize.md`](references/build-sign-notarize.md) — 패키징 스크립트, ad-hoc vs Developer ID, notarization, 미서명 테스트 배포.

## 근거 / evidence

아래 커밋·파일 참조는 모두 **내부 비공개 골격 저장소** 기준이다(이 저장소에서는 조회되지 않는다).

- 골격 저장소 — Steno, b3os.app 실사용 검증
- 패턴 박제: 골격의 `docs/Architecture.md` "주요 결정" Q/A (커밋 `5f80a8e`)
- viewport 근본해결: 골격의 `WebView.swift`·`AppShell.swift` (커밋 `c626beb`, `ac8ed27` — 측정 기반)
- **레시피 재현 evidence**: 이 레시피(골격의 `package-macos-app.sh`)로 빌드한 `b3os.app` → `.build/b3os-latest.zip`(397KB, 2026-06-24 빌드), the team lead 실기 확인 + `<dashboard-domain>` 배포본. 빌드 로그는 이 스킬의 [`references/build-evidence.md`](references/build-evidence.md).

## 유지보수 — owner · 갱신 트리거

- **owner / 업데이트 책임자: agent A, developer** (둘이 함께 유지·교차리뷰).
- **언제 갱신하나(트리거)**:
  - 골격(`mac-iphone-shell`)의 WebView/창 chrome/패키징 스크립트가 바뀔 때 → 이 스킬의 references 동기화.
  - 새 macOS/Xcode에서 빌드·viewport가 깨질 때 → 전제 핀 버전 갱신 + 회귀주의 보강.
  - notarization/서명 흐름(Apple 정책)이 바뀔 때 → `build-sign-notarize.md` 갱신.
  - 새 실전 앱을 이 레시피로 만들 때 → evidence에 추가(관측 누적).