|
| 1 | +# Remin 구현 분석 & App Store 업로드 준비 |
| 2 | + |
| 3 | +이 문서는 현재 `Remin` 저장소 기준으로: |
| 4 | +1) 구현된 기능/아키텍처를 요약하고 |
| 5 | +2) App Store(주로 iOS) 업로드/심사에 필요한 준비사항과 레포 기준 갭을 정리합니다. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## 1) 앱 개요 (현재 구현 기준) |
| 10 | + |
| 11 | +- **타깃**: SwiftUI 기반 멀티플랫폼(단일 타깃) 구성으로 보이며, Xcode 설정상 `iphoneos/macosx/xros`까지 `SUPPORTED_PLATFORMS`에 포함되어 있습니다. |
| 12 | + - 설정: `Remin.xcodeproj/project.pbxproj` (`SUPPORTED_PLATFORMS`) |
| 13 | +- **핵심 컨셉**: Photos 라이브러리의 여행 사진을 “세션(Session) → 활동(Activity) → 장소(Location) → 비주얼 그룹(VisualGroup)”로 정리하고, 검색(Discovery) 및 콘텐츠 생성(달력/포토북/프레임/비디오)을 제공합니다. |
| 14 | +- **온디바이스 처리 중심**: PhotoKit/Vision/CoreML(SemanticEmbedding) 기반 분석과 SwiftData 로컬 저장이 중심입니다. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## 2) 사용자 플로우(큰 흐름) |
| 19 | + |
| 20 | +1. **Photos 권한 요청/앨범 로드** |
| 21 | + - `Remin/Core/Services/PhotoLibraryService.swift` |
| 22 | +2. **앨범 선택 → 세션 생성** |
| 23 | + - UI: `Remin/Features/AlbumSelection/*` |
| 24 | + - 모델: `Remin/Core/Models/CurationSession.swift` |
| 25 | +3. **백그라운드 분석(세션 처리)** |
| 26 | + - 오케스트레이션: `Remin/Core/Services/SessionProcessingService.swift` |
| 27 | + - 파이프라인: `Remin/Core/Clustering/ClusteringPipeline.swift` |
| 28 | + - 캐시: `Remin/Core/Services/AnalysisCacheService.swift` |
| 29 | +4. **결과 탐색/리뷰** |
| 30 | + - 활동 뷰: `Remin/Features/Activities/ActivitiesView.swift` |
| 31 | + - 리뷰 뷰: `Remin/Features/Review/ReviewView.swift` |
| 32 | +5. **Discovery(자연어 검색)** |
| 33 | + - `Remin/Core/Discovery/*` |
| 34 | +6. **콘텐츠 생성** |
| 35 | + - 비디오 생성: `Remin/Features/VideoGeneration/*`, `Remin/Core/Services/VideoGenerationCoordinator.swift`, `Remin/Core/Services/VideoGenerationService.swift` |
| 36 | + - 달력: `Remin/Features/CalendarCreator/*`, `Remin/Core/Services/CalendarExportService.swift` |
| 37 | + - 스토리(HTML 등): `Remin/Core/Services/StoryHTMLExportService.swift` |
| 38 | +7. **여정 자동 감지/추천** |
| 39 | + - `Remin/Features/JourneyDiscovery/*` |
| 40 | + - `Remin/Core/Services/LibraryEventDetectionService.swift` |
| 41 | + - `Remin/Core/Services/TravelRecommendationService.swift` |
| 42 | + |
| 43 | +--- |
| 44 | + |
| 45 | +## 3) 아키텍처 요약 (디렉터리 관점) |
| 46 | + |
| 47 | +- `Remin/App/` |
| 48 | + - 앱 엔트리 및 루트 UI/오버레이: `Remin/App/ReminApp.swift` |
| 49 | +- `Remin/Core/Models/` |
| 50 | + - SwiftData 모델(세션/활동/사진/컬렉션/비디오 상태 등) |
| 51 | +- `Remin/Core/Services/` |
| 52 | + - PhotoKit/분석/캐시/생성/검색 등 “도메인 서비스” 모음 |
| 53 | +- `Remin/Core/Clustering/` |
| 54 | + - 4단계 계층 클러스터링 알고리즘/파이프라인 |
| 55 | +- `Remin/Core/Discovery/` |
| 56 | + - Query 파싱 → 규칙 평가 → 결과 집계/랭킹 |
| 57 | +- `Remin/Features/` |
| 58 | + - SwiftUI 화면 단위 기능 모듈 |
| 59 | +- `Remin/Design/` |
| 60 | + - 테마/컴포넌트/기능 게이팅(Apple Intelligence 등) |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +## 4) 처리 파이프라인(세션 분석) 핵심 |
| 65 | + |
| 66 | +`Remin/Core/Services/SessionProcessingService.swift` → `Remin/Core/Clustering/ClusteringPipeline.swift` 흐름으로 동작합니다. |
| 67 | + |
| 68 | +- **메타데이터 추출**: `PHAsset`에서 촬영시각/GPS 등 추출 |
| 69 | +- **Vision 분석**: 장면/얼굴/FeaturePrint 등(캐시 지원) |
| 70 | +- **품질 분석**: Vision Aesthetics API 기반(캐시 지원) |
| 71 | +- **시맨틱 임베딩(Optional)**: MobileCLIP(CoreML)로 임베딩 생성 및 유사도 점수 활용 |
| 72 | + - 모델 리소스: `Remin/Resources/MobileCLIP_*Encoder.mlpackage`, `Remin/Resources/vocab.json`, `Remin/Resources/merges.txt` |
| 73 | +- **클러스터링**: |
| 74 | + - Level 1 시간(Temporal) |
| 75 | + - Level 2 GPS(DBSCAN) |
| 76 | + - Level 3 시각 유사도 |
| 77 | + - Level 4 대표 사진 선택 |
| 78 | + |
| 79 | +--- |
| 80 | + |
| 81 | +## 5) Discovery(자연어 검색) 구조 |
| 82 | + |
| 83 | +- 진입점: `Remin/Core/Discovery/DiscoveryEngine/DiscoveryService.swift` |
| 84 | +- Query 파싱: `Remin/Core/Discovery/DiscoveryEngine/SemanticQueryParser.swift` |
| 85 | +- 규칙 레지스트리/규칙들: `Remin/Core/Discovery/Rules/*` |
| 86 | +- 결과는 규칙별 매칭을 집계하고 다양성 필터를 적용한 뒤 상위 N개를 반환합니다. |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## 6) 권한/프라이버시(레포 기준 현황) |
| 91 | + |
| 92 | +### 권한 문자열(Info.plist) |
| 93 | +- Photos 접근: 필요 |
| 94 | + - `NSPhotoLibraryUsageDescription` |
| 95 | + - `NSPhotoLibraryAddUsageDescription` |
| 96 | +- 백그라운드 처리(BGTaskScheduler): 코드 사용 중 |
| 97 | + - 식별자: `com.remin.photo-processing` (`Remin/Core/Services/BackgroundTaskService.swift`) |
| 98 | + |
| 99 | +### Privacy Manifest |
| 100 | +- `Remin/PrivacyInfo.xcprivacy` 존재 |
| 101 | + - Tracking: `false` |
| 102 | + - CollectedDataTypes: Photos/Videos(앱 기능 목적) |
| 103 | + - Required Reason API: UserDefaults, FileTimestamp |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## 7) App Store 업로드 준비 체크리스트 (실무용) |
| 108 | + |
| 109 | +### A. App Store Connect/계정 |
| 110 | +- Apple Developer Program 등록(조직/개인) |
| 111 | +- App Store Connect에서 앱 생성(플랫폼 iOS 기준) |
| 112 | +- Bundle ID/App ID 생성 및 앱명/서브타이틀/카테고리/연령등급 설정 |
| 113 | + |
| 114 | +### B. Xcode 프로젝트/서명/버전 |
| 115 | +- `PRODUCT_BUNDLE_IDENTIFIER` 확정 및 중복 없는 값 사용 |
| 116 | +- `MARKETING_VERSION`(예: 1.0.0), `CURRENT_PROJECT_VERSION`(예: 1) 관리 |
| 117 | +- Release 설정으로 Archive 가능해야 함(코드사인/프로비저닝/팀 설정) |
| 118 | + |
| 119 | +### C. 권한/백그라운드/기기 지원 |
| 120 | +- Photos 권한 거부/제한(“제한된 사진” 포함) 시 UX가 깨지지 않는지 확인 |
| 121 | +- BGTaskScheduler 사용 시: |
| 122 | + - Info.plist에 `BGTaskSchedulerPermittedIdentifiers` 포함 |
| 123 | + - Info.plist에 `UIBackgroundModes = processing` 포함 |
| 124 | + - 실제로 백그라운드에서 실행되는 작업이 사용자 가치/설명 가능해야 함(심사 메모에 설명 권장) |
| 125 | + |
| 126 | +### D. 프라이버시/정책/심사 대응 |
| 127 | +- App Store Connect의 **App Privacy 설문** 작성(실제 동작과 일치해야 함) |
| 128 | +- Privacy Policy URL/Support URL 준비(웹에 호스팅 필요) |
| 129 | + - (권장) GitHub Pages로 `privacy.html`, `support.html` 제공 |
| 130 | + - 템플릿(이 레포): `docs/privacy.html`, `docs/support.html` |
| 131 | + - 예시(리포 이름이 `remin-support`인 경우): |
| 132 | + - Support URL: `https://puritysb.github.io/remin-support/` |
| 133 | + - Privacy Policy URL: `https://puritysb.github.io/remin-support/privacy.html` |
| 134 | +- (해당 시) “데이터 삭제/세션 삭제” 경로 명확히 제공 |
| 135 | +- (해당 시) 서드파티 모델/데이터 파일(MobileCLIP, vocab/merges 등) 라이선스/출처 정리 및 고지 문서 준비(권장) |
| 136 | + |
| 137 | +### E. 메타데이터/에셋 |
| 138 | +- 앱 아이콘, 스크린샷(iPhone/iPad), 앱 미리보기(선택) |
| 139 | +- 기능 설명/키워드/프로모션 텍스트/리뷰 노트(특히 Photos 접근, 백그라운드 분석, iCloud 사진 처리 여부) |
| 140 | + |
| 141 | +### F. 배포 플로우 |
| 142 | +- Xcode: Archive → Validate → Distribute(App Store Connect) |
| 143 | +- TestFlight 내부/외부 테스트 |
| 144 | +- 최종 제출 및 심사 대응(리뷰 노트/테스트 계정 필요 여부 등) |
| 145 | + |
| 146 | +--- |
| 147 | + |
| 148 | +## 8) 레포 기준 “업로드 전” 확인/수정이 필요한 지점(중요) |
| 149 | + |
| 150 | +아래는 “지금 상태 그대로 App Store 업로드”를 가로막을 가능성이 높은 항목들입니다. |
| 151 | + |
| 152 | +1. **iOS 전용 배포 설정 정리** |
| 153 | + - iOS 전용 릴리즈 기준: |
| 154 | + - `SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"` |
| 155 | + - `IPHONEOS_DEPLOYMENT_TARGET = 26.0` |
| 156 | + - `TARGETED_DEVICE_FAMILY = "1,2"` (iPhone/iPad) |
| 157 | + - 설정: `Remin.xcodeproj/project.pbxproj` |
| 158 | + |
| 159 | +2. **Info.plist 반영 방식** |
| 160 | + - iOS 전용 릴리즈 기준으로 `INFOPLIST_FILE = Remin/Info.plist`를 사용하도록 정리했습니다. |
| 161 | + - BGTask/BackgroundModes/Photos/Location 문자열은 `Remin/Info.plist`에 선언되어야 합니다. |
| 162 | + |
| 163 | +3. **entitlements 정리** |
| 164 | + - macOS App Sandbox 키를 포함한 `Remin/Remin.entitlements`는 iOS 제출에 필요하지 않으므로 iOS 전용 릴리즈에서는 사용하지 않는 편이 안전합니다. |
| 165 | + |
| 166 | +4. **Foundation Models(Apple Intelligence) 사용 조건(availability/import) 정리 필요** |
| 167 | + - 여러 파일에서 `iOS 26` 기준으로 `@available` / `#available`이 사용됩니다. |
| 168 | + - 실제 목표 OS에 맞춰 조건과 fallback(Tier 1)이 빌드/런타임 모두 안전한지 점검이 필요합니다. |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## 9) 추천 작업 순서(최소 리스크) |
| 173 | + |
| 174 | +1. iOS 전용 배포 설정 정리 |
| 175 | +2. Info.plist에 BGTask/권한 키 반영 |
| 176 | +3. entitlements 제거/정리(iOS용만) |
| 177 | +4. App Privacy 설문/Privacy Policy URL/Support URL 준비 |
| 178 | +5. TestFlight로 권한/백그라운드/대용량 라이브러리 성능 검증 |
0 commit comments