Skip to content

iOS Setup

Barbelic iOS 앱은 원격 React 앱을 여는 Capacitor/WKWebView 셸이며 Kakao, Google, Apple 로그인에 공통 Supabase PKCE 흐름을 사용한다.

준비 및 실행

  • macOS에 Xcode 정식 앱을 설치하고 라이선스와 추가 컴포넌트 설치를 완료한다.
  • iPhone을 연결하고 기기 신뢰를 허용한다.
bash
npm ci
npm run build
npm run ios:sync
npm run ios:open

Xcode의 barbelic shared scheme과 App target에서 Team을 선택하고 Bundle Identifier com.dekerd.barbelic를 확인한 뒤 실기기에서 실행한다. scheme 이름과 Barbelic.app 산출물은 Capacitor CLI 실행 경로에도 동일하게 사용된다. TestFlight/App Store 배포에는 Apple Developer Program이 필요하다.

Build configuration

Debug/Release xcconfig는 다음 값을 Info.plist로 주입한다.

  • BARBELIC_SERVER_ORIGIN: WebView가 여는 정규 origin https://www.barbelic.com.
  • BARBELIC_SUPABASE_AUTH_ORIGIN: authorize URL을 허용할 정확한 Supabase origin
  • BARBELIC_CALLBACK_SCHEME: 새 앱의 custom URL scheme인 barbelic

barbelic://auth/callback은 Xcode URL Types에 등록되어 있어야 한다. Supabase Dashboard의 Redirect URLs에도 barbelic://auth/callback**을 등록한다.

App Store 제출 준비물 (심사 #665 Phase 8, 2026-09-02)

  • App/PrivacyInfo.xcprivacy — 앱 타깃의 privacy manifest. Apple은 2024-05-01부터 "사유 필요 API"(UserDefaults 등)를 쓰면서 이 파일이 없는 앱을 App Store Connect 업로드 단계에서 거부한다(ITMS-91053). Capacitor 프레임워크는 자기 manifest를 갖지만 앱 코드의 UserDefaults 사용은 앱 몫이다. 수집 데이터 유형 목록은 App Store Connect의 App Privacy 라벨과 같아야 한다 — 라벨을 바꾸면 이 파일도 같이 바꾼다. 트래킹 없음.
  • Info.plist 권한 문구 3종 — NSCameraUsageDescription·NSPhotoLibraryUsageDescription(프로필 사진 변경의 웹 파일 선택기가 "사진 찍기 / 사진 보관함"을 띄운다 — 문구가 없으면 카메라 선택 시 시스템이 앱을 강제 종료한다, 2026-09-03 재점검) · NSPhotoLibraryAddUsageDescription(세션 이미지 저장).
  • Info.plistITSAppUsesNonExemptEncryption = false — 표준 HTTPS만 쓰므로 수출 규정 예외. 없으면 빌드 업로드마다 암호화 질문에 답해야 한다.
  • 오프라인 안내 페이지 — capacitor.config.jsonserver.errorPath(offline.html)가 번들 public/offline.html(저장소 public/offline.html, npm run buildnpm run ios:sync로 복사)을 가리킨다. 서버 연결 실패 시 검은 화면 대신 이 페이지가 뜬다. 동작 계약은 contracts/native-bridge.md의 Offline page.
  • 데이터 내보내기 — 앱에서는 다운로드 링크 대신 shareFile 브리지로 iOS 공유 창을 연다 (같은 문서의 Share file).

Windows에서는 Swift를 컴파일할 수 없으므로 위 항목 중 Swift 변경(로드 실패 처리·공유 창)은 macOS Xcode 빌드에서 컴파일이 확인된다. 파일 등록·plist 키·config 값은 tests/react/iosStoreSubmissionContract.test.mjs가 단언한다.

Social login flow

  1. 웹이 선택한 provider로 로그인은 Supabase signInWithOAuth, 계정 연결은 linkIdentity를 호출하고 PKCE verifier와 32-byte transaction ID를 만든다. verifier는 전체 session과 분리해 iOS Keychain에 최대 10분만 저장한다.
  2. iOS는 startSocialLogin 메시지의 action/provider/transaction을 바인딩한다. 로그인 URL은 Supabase origin·S256 challenge·custom redirect를, 연결 URL은 provider별 공식 authorize endpoint와 정확한 Supabase callback을 검증한다.
  3. iOS가 authorize URL을 ASWebAuthenticationSession으로 연다. 단 Apple 로그인 (action sign-in, provider apple)은 시스템 시트(ASAuthorizationController)를 띄우고, 돌려받은 identity token과 원문 nonce를 barbelic:native-auth detail { provider, idToken, nonce }로 넘긴다 — 웹이 signInWithIdToken으로 세션을 만들므로 4~6단계의 callback URL 교환은 없다. Sign in with Apple capability (App/App.entitlements)와 Supabase Apple Client IDs의 번들 ID가 전제다.
  4. provider 인증 후 Supabase가 barbelic://auth/callback?auth_action=...&provider=...&transaction_id=...&code=...로 돌려보낸다.
  5. iOS가 pending action/provider/transaction/10분 TTL을 검증하고 1회 소비한다.
  6. 웹이 Keychain의 verifier를 복구해 code를 Supabase session으로 교환하고 verifier를 삭제한다. refresh session은 별도 Keychain item에 보관한다.

자세한 메시지 형식은 contracts/native-bridge.md, provider 설정은 social-auth.md를 따른다.

실기기 확인

  • rollout gate를 연 뒤 로그인 화면에 Kakao, Google, Apple 세 버튼이 모두 보이는가
  • 각 버튼이 WebView 내부 이동이 아니라 외부 인증 세션을 여는가 (Apple 로그인만 시스템 시트 — Face ID/암호 — 가 뜨고, Apple 계정 연결은 여전히 웹 시트인가)
  • 취소하거나 provider 오류가 발생하면 버튼 pending 상태가 해제되는가
  • 성공 callback에는 code만 있고 access/refresh/ID token이 없는가
  • 로그인 뒤 홈, 세션, 종목, 내 정보 탭과 운동 시작 화면이 정상인가
  • 앱을 종료 후 다시 열어도 Keychain session으로 로그인이 복원되는가
  • provider callback 직전에 WebView 또는 앱이 재시작돼도 로그인이 완료되는가
  • iframe 또는 다른 origin에서 native bridge 호출 시 무시되는가
  • 로그인된 사용자가 내 정보에서 사용하지 않은 provider를 연결하고, 재로그인 후에도 같은 auth.users.id와 기존 데이터를 유지하는가

Windows에서는 Swift를 컴파일할 수 없으므로 이 변경의 최종 검증에는 macOS Xcode build와 위 실기기 시나리오가 필수다.