diff --git a/myApp/Keging/CLAUDE.md b/myApp/Keging/CLAUDE.md index eb95116..9eeb9cb 100644 --- a/myApp/Keging/CLAUDE.md +++ b/myApp/Keging/CLAUDE.md @@ -20,7 +20,7 @@ | 최소 OS | iOS 18.0 / watchOS 10.0 | | 수익 모델 | **완전 무료** — 광고·결제 일절 없음. CloudKit 없음. HealthKit은 운동·강도·활성 에너지 **쓰기** + 심박·활성 에너지 **읽기**(워치 심박 세션의 센서 수집용 — 폰 앱 자체는 조회 안 함, §3.7·§3.8) | | 언어 | **한국어(원문)/영어/일본어** — String Catalog(타깃별 `Localizable.xcstrings`, InfoPlist 포함). 설정 → 언어(시스템/한국어/English/日本語)에서 앱 내 전환: `AppleLanguages` 오버라이드, **완전 종료 후 재실행 시 적용**(하루 다님 검증 방식). 워치·Live Activity·단축어 표기는 각자의 시스템 언어를 따름 | -| 현재 상태 (2026-09-05) | **9차 반영 완료(2026-09-05) — TestFlight 재테스트 대기: 아이폰 시작 세트의 워치 심박 측정(§3.8).** 사용자 TestFlight 피드백('워치 연동됨' 배지가 워치 앱 포그라운드에서만 켜짐 — 원래 의도는 폰으로 할 때 워치가 심박을 재는 것)으로 재설계: ①폰 시작 → `HKHealthStore.startWatchApp`으로 워치 앱을 깨워 HKWorkoutSession을 열고 폰으로 **미러링**(watchOS 10+/iOS 17+ 공식 API) — 워치는 센서 역할만(무진동), 심박은 미러링 채널로 폰 운동 화면에 표시, 완주 시 워치 라이브 빌더가 심박·활성 에너지 실측으로 건강 저장(폰 사후 저장은 폴백) ②첫 화면 **워치 배지·사전 확인 창 폐지**, 대신 운동 화면 횟수 아래 상태 줄(연결 중/♥bpm/아이폰만) + 워치 앱을 못 열면 경고 알럿(설정 > 애플워치 '워치 연결 실패 경고' 토글 — 기존 `app.watchWarn` 키 재사용) ③워치 시작은 종전대로 워치 진동·워치 저장. 시뮬로는 startWatchApp·미러링 검증 불가 — **실기기 재테스트 항목**: 폰 시작 → 워치 앱 자동 기동·'아이폰에서 진행 중' 화면·폰에 ♥bpm 표시, 완주 후 건강 앱에 심박 포함 운동 1건(중복 없음), 워치 미착용/멀리 → 30초 안에 경고 알럿 + 폰 사후 저장, 중단 → 건강 기록 없음. 이전: **App Store 배포 자료 작성 완료(2026-09-05) — 사용자 등록 단계 대기.** `Marketing/`(하루 다님 구성 이식: 이름·부제목/설명/키워드/프로모션/새 기능/리뷰 메모 3언어 + 스크린샷 아이폰 9장·워치 3장 × ko/en/ja 원본+합성, 합성 도구·재촬영 요령·출시 체크리스트는 `Marketing/README.md`) + `Docs/PRIVACY.md`(개인정보처리방침 3언어) + `PrivacyInfo.xcprivacy` 3타깃(ITMS-91053 대응, 코드 무변경). **사용자 다음 단계**: ①GitHub 공개 저장소 `notalentprogrammer/Keging`에 PRIVACY.md 게시(URL이 description·review-notes에 박혀 있음) ②ASC 앱 생성·자료 입력(review-notes.txt) ③Archive → 업로드 → TestFlight → 제출. 심사 예상 쟁점: 백그라운드 오디오 모드(2.5.4) — 리뷰 메모에 용도 소명 문구 준비됨. 코드·버전(1.0/빌드 1) 무변경. 이전: **8차 반영 완료, 재테스트 대기.** 8차(워치 수정 2건): ①기본·톡톡 진동이 너무 약함 → **.notification(알림급)으로 교체**(§3.3) ②세팅 크라운 충돌 → **목록은 스크롤 전용, 숫자 항목은 눌러서 크라운 편집 화면**(CrownValueEditor, §3.6). 7차(플랫폼 결정: 현행 iOS+워치 유지): ①폰 첫 화면 시작 버튼 위 **워치 연결 배지**(연결됨=그린 전파 아이콘/미연결·미연동=슬래시. ⚠️iOS 제약상 '연결됨'은 워치에서 케깅이 켜져 있을 때만 — §4) + **미연결 시작 확인 창**(기록은 동일함을 안내, 설정 > 애플워치 토글로 끔, 단축어·autoStart는 경고 없이 통과) ②**세팅 기기별 독립** — config 동기화 전면 제거(§3.6), 워치는 시작 화면 **왼쪽 스와이프 세팅 페이지**(TabView .page: 준비/수축/이완/횟수 스테퍼 + 진동 2종 피커(선택 즉시 미리 울림) + 운동 유형·강도, 요약 라인 즉시 반영) ③**워치 진동 강화 재설계**(§3.3: .start/.stop급 강한 시퀀스). 6차: DI 컴팩트=두 색 점+남은 시간, 확장=잠금화면과 동일 실시간 현황, 통계 하루 탭 꺾은선 제거. 5차: LA 완전 자가 렌더링(무갱신 — 실기기 정상 확인). "컴팩트에 국면 글자"는 iOS 제약으로 불가 확정(서버 푸시만 가능 — 기각). **재테스트(사용자)**: 워치 세팅 페이지·강한 진동 3종+완료, 폰 배지·경고 창, 워치 기록이 폰 통계 합류 | 5차 실기기 판독: 진동은 끝까지 제때 = 앱은 백그라운드 생존, 그러나 **국면 라벨·횟수는 항상 수축 2회차(4번째 전송)에서 동결 + 진행바만 계속 흐름** → 백그라운드 LA 갱신을 시스템이 예산제로 폐기하는 것으로 확정, staleDate 재렌더도 시뮬 실측 결과 발화 안 함 → **갱신 자체를 없앤 설계로 전환**(§3.4): 시작 시 1회 등록(`ensureStarted`), 이후 update 호출 0회, 화면은 전부 시스템 렌더(타임라인 바+플레이헤드+남은 시간)와 영원히 참인 정적 정보(수축·이완 범례, 세트 구성)만. 국면 라벨·횟수 텍스트는 LA에서 제거(국면=진동+플레이헤드 색, 횟수=앱 열면). 시뮬 검증: 등록 후 갱신 없이 35초간 카운트다운 4:57→4:27 정확·미니 바 전진·완주 시 DI 해제, 3종 빌드 그린·경고 0·l10n 0/0/0. 이전 라운드: 3차(햅틱 엔진 세션 부착·키퍼 하드닝·하트비트·워치 세팅 pull·완료 진동·오늘의 타임라인·칼로리 정합), 4차(디더 노이즈·브리지 태스크·타임라인 시각 라벨 제거). **재테스트 항목(사용자, 아이폰)**: ①DI 컴팩트(미니 타임라인+남은 시간)·확장·잠금화면 배너(범례+큰 남은 시간+바+세트 구성)가 세트 끝까지 흐르는지 — 이제 갱신이 없어 구조적으로 동결 불가 ②완료 진동·백그라운드 진동(이미 정상 확인됨)·워치 세팅 동기화·칼로리 | +| 현재 상태 (2026-09-05) | **9차 반영 완료(2026-09-05) — 버전 1.0(빌드 2)로 재업로드·TestFlight 재테스트 대기: 아이폰 시작 세트의 워치 심박 측정(§3.8).** ⚠️빌드 1은 9차 이전 코드로 이미 업로드돼 있었는데 9차 커밋에서 빌드 번호를 안 올려 ASC에 안 뜬 사고(사용자 발견) — **코드를 바꿔 재업로드할 때는 세 타깃 CURRENT_PROJECT_VERSION을 반드시 올릴 것.** 사용자 TestFlight 피드백('워치 연동됨' 배지가 워치 앱 포그라운드에서만 켜짐 — 원래 의도는 폰으로 할 때 워치가 심박을 재는 것)으로 재설계: ①폰 시작 → `HKHealthStore.startWatchApp`으로 워치 앱을 깨워 HKWorkoutSession을 열고 폰으로 **미러링**(watchOS 10+/iOS 17+ 공식 API) — 워치는 센서 역할만(무진동), 심박은 미러링 채널로 폰 운동 화면에 표시, 완주 시 워치 라이브 빌더가 심박·활성 에너지 실측으로 건강 저장(폰 사후 저장은 폴백) ②첫 화면 **워치 배지·사전 확인 창 폐지**, 대신 운동 화면 횟수 아래 상태 줄(연결 중/♥bpm/아이폰만) + 워치 앱을 못 열면 경고 알럿(설정 > 애플워치 '워치 연결 실패 경고' 토글 — 기존 `app.watchWarn` 키 재사용) ③워치 시작은 종전대로 워치 진동·워치 저장. 시뮬로는 startWatchApp·미러링 검증 불가 — **실기기 재테스트 항목**: 폰 시작 → 워치 앱 자동 기동·'아이폰에서 진행 중' 화면·폰에 ♥bpm 표시, 완주 후 건강 앱에 심박 포함 운동 1건(중복 없음), 워치 미착용/멀리 → 30초 안에 경고 알럿 + 폰 사후 저장, 중단 → 건강 기록 없음. 이전: **App Store 배포 자료 작성 완료(2026-09-05) — 사용자 등록 단계 대기.** `Marketing/`(하루 다님 구성 이식: 이름·부제목/설명/키워드/프로모션/새 기능/리뷰 메모 3언어 + 스크린샷 아이폰 9장·워치 3장 × ko/en/ja 원본+합성, 합성 도구·재촬영 요령·출시 체크리스트는 `Marketing/README.md`) + `Docs/PRIVACY.md`(개인정보처리방침 3언어) + `PrivacyInfo.xcprivacy` 3타깃(ITMS-91053 대응, 코드 무변경). **사용자 다음 단계**: ①GitHub 공개 저장소 `notalentprogrammer/Keging`에 PRIVACY.md 게시(URL이 description·review-notes에 박혀 있음) ②ASC 앱 생성·자료 입력(review-notes.txt) ③Archive → 업로드 → TestFlight → 제출. 심사 예상 쟁점: 백그라운드 오디오 모드(2.5.4) — 리뷰 메모에 용도 소명 문구 준비됨. 버전 1.0(빌드 1)로 TestFlight 업로드됨(사용자). 이전: **8차 반영 완료, 재테스트 대기.** 8차(워치 수정 2건): ①기본·톡톡 진동이 너무 약함 → **.notification(알림급)으로 교체**(§3.3) ②세팅 크라운 충돌 → **목록은 스크롤 전용, 숫자 항목은 눌러서 크라운 편집 화면**(CrownValueEditor, §3.6). 7차(플랫폼 결정: 현행 iOS+워치 유지): ①폰 첫 화면 시작 버튼 위 **워치 연결 배지**(연결됨=그린 전파 아이콘/미연결·미연동=슬래시. ⚠️iOS 제약상 '연결됨'은 워치에서 케깅이 켜져 있을 때만 — §4) + **미연결 시작 확인 창**(기록은 동일함을 안내, 설정 > 애플워치 토글로 끔, 단축어·autoStart는 경고 없이 통과) ②**세팅 기기별 독립** — config 동기화 전면 제거(§3.6), 워치는 시작 화면 **왼쪽 스와이프 세팅 페이지**(TabView .page: 준비/수축/이완/횟수 스테퍼 + 진동 2종 피커(선택 즉시 미리 울림) + 운동 유형·강도, 요약 라인 즉시 반영) ③**워치 진동 강화 재설계**(§3.3: .start/.stop급 강한 시퀀스). 6차: DI 컴팩트=두 색 점+남은 시간, 확장=잠금화면과 동일 실시간 현황, 통계 하루 탭 꺾은선 제거. 5차: LA 완전 자가 렌더링(무갱신 — 실기기 정상 확인). "컴팩트에 국면 글자"는 iOS 제약으로 불가 확정(서버 푸시만 가능 — 기각). **재테스트(사용자)**: 워치 세팅 페이지·강한 진동 3종+완료, 폰 배지·경고 창, 워치 기록이 폰 통계 합류 | 5차 실기기 판독: 진동은 끝까지 제때 = 앱은 백그라운드 생존, 그러나 **국면 라벨·횟수는 항상 수축 2회차(4번째 전송)에서 동결 + 진행바만 계속 흐름** → 백그라운드 LA 갱신을 시스템이 예산제로 폐기하는 것으로 확정, staleDate 재렌더도 시뮬 실측 결과 발화 안 함 → **갱신 자체를 없앤 설계로 전환**(§3.4): 시작 시 1회 등록(`ensureStarted`), 이후 update 호출 0회, 화면은 전부 시스템 렌더(타임라인 바+플레이헤드+남은 시간)와 영원히 참인 정적 정보(수축·이완 범례, 세트 구성)만. 국면 라벨·횟수 텍스트는 LA에서 제거(국면=진동+플레이헤드 색, 횟수=앱 열면). 시뮬 검증: 등록 후 갱신 없이 35초간 카운트다운 4:57→4:27 정확·미니 바 전진·완주 시 DI 해제, 3종 빌드 그린·경고 0·l10n 0/0/0. 이전 라운드: 3차(햅틱 엔진 세션 부착·키퍼 하드닝·하트비트·워치 세팅 pull·완료 진동·오늘의 타임라인·칼로리 정합), 4차(디더 노이즈·브리지 태스크·타임라인 시각 라벨 제거). **재테스트 항목(사용자, 아이폰)**: ①DI 컴팩트(미니 타임라인+남은 시간)·확장·잠금화면 배너(범례+큰 남은 시간+바+세트 구성)가 세트 끝까지 흐르는지 — 이제 갱신이 없어 구조적으로 동결 불가 ②완료 진동·백그라운드 진동(이미 정상 확인됨)·워치 세팅 동기화·칼로리 | ## 2. 빌드·검증 환경 diff --git a/myApp/Keging/Keging.xcodeproj/project.pbxproj b/myApp/Keging/Keging.xcodeproj/project.pbxproj index 1da0b98..4389488 100644 --- a/myApp/Keging/Keging.xcodeproj/project.pbxproj +++ b/myApp/Keging/Keging.xcodeproj/project.pbxproj @@ -489,7 +489,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = IOS/Keging.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -530,7 +530,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = IOS/Keging.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -571,7 +571,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "KegingWatch Watch App/KegingWatch Watch App.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -606,7 +606,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "KegingWatch Watch App/KegingWatch Watch App.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -641,7 +641,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = KegingWidgetsExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = KegingWidgets/Info.plist; @@ -672,7 +672,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = KegingWidgetsExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = 5GNS4Z2SYT; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = KegingWidgets/Info.plist; diff --git a/myApp/Keging/Marketing/AppStore/review-notes.txt b/myApp/Keging/Marketing/AppStore/review-notes.txt index 0b7ab62..daca5e9 100644 --- a/myApp/Keging/Marketing/AppStore/review-notes.txt +++ b/myApp/Keging/Marketing/AppStore/review-notes.txt @@ -33,7 +33,7 @@ Keging is a free Kegel exercise timer with no account, no ads, and no in-app pur The app provides no medical advice; a note in the description says to consult a professional in case of pain or a medical condition. [아카이브 → 업로드 체크] -- 세 타깃 버전 일치: iOS 1.0(1) / 워치 1.0(1) / 위젯 1.0(1) — 워치 버전이 다르면 업로드 거부 +- 세 타깃 버전 일치: iOS 1.0(2) / 워치 1.0(2) / 위젯 1.0(2) — 워치 버전이 다르면 업로드 거부. 재업로드는 빌드 번호 증가 필수(1.0(1)은 이미 업로드됨) - 스킴 Keging + Any iOS Device (arm64) → Product → Archive → Distribute → App Store Connect → Upload - 재업로드는 빌드 번호 증가 필수 - TestFlight 실기기 확인: 진동 3종·완료 진동·백그라운드 진동·DI·워치 기록 합류·건강 기록 diff --git a/myApp/Keging/Marketing/README.md b/myApp/Keging/Marketing/README.md index 1218c82..8dd005c 100644 --- a/myApp/Keging/Marketing/README.md +++ b/myApp/Keging/Marketing/README.md @@ -121,7 +121,7 @@ simctl에는 터치 주입이 없다. `open -a Simulator`로 창을 띄운 뒤 * - [ ] 출시 방식: 자동 또는 수동 ### ⑤ 아카이브 → 업로드 → TestFlight (⏳ 처리 10~60분) -- [ ] 세 타깃 버전·빌드 일치(1.0/1) 확인 → 스킴 Keging + Any iOS Device → Archive → Distribute → Upload +- [ ] 세 타깃 버전·빌드 일치(1.0/2 — 빌드 1은 TestFlight에 이미 업로드됨) 확인 → 스킴 Keging + Any iOS Device → Archive → Distribute → Upload - [ ] 수출 규정 질문에 '아니요'(표준 암호화만) - [ ] TestFlight 내부 테스트: 진동 3종·완료 진동·백그라운드 진동·DI/잠금화면·워치 기록 합류·건강 기록