diff --git a/README.md b/README.md new file mode 100644 index 0000000..b460fd6 --- /dev/null +++ b/README.md @@ -0,0 +1,185 @@ +AppIcon + + +## 사하라 + +> 사진을 포토카드로 만들어 기록, 편집하고 탐색할 수 있는 사진 아카이빙 앱 + +[AppStore Link](https://apps.apple.com) + +image 6 | image 7 | IMG_2300 | IMG_2492 | +|:--:|:--:|:--:|:--:| + +|구분|내용| +|:--:|:--| +|**팀 인원**|1명 / 기획, 디자인, 개발| +|**기획 및 개발 기간**|2025.09 - 2025.10 (3주, 핵심 개발 기간 1주)| +|**최소지원버전**|iOS 16.0+| + +## 핵심 기능 + +- 사진 촬영 및 포토카드 편집 - 스티커, 필터, 펜, 메모, 사진 분류 +- 날짜/지역/테마/폴더별 사진 분류 +- 비밀 카드 잠금 설정 +- 카드 검색 및 정렬 통계 확인 +- 서비스 소식 알림 수신 +- 4개 국어 지원(한국어, 영어, 중국어, 일본어) + +## 기술 스택 + +| 분류 | 기술 스택 | +|:--:|:--| +| **UI Framework** | ![UIKit](https://img.shields.io/badge/UIKit-2396F3?style=flat-square&logo=uikit&logoColor=white) ![SnapKit](https://img.shields.io/badge/SnapKit-FF6B6B?style=flat-square&logo=swift&logoColor=white) | +| **Asynchronous Programming** | ![RxSwift](https://img.shields.io/badge/RxSwift-B7178C?style=flat-square&logo=reactivex&logoColor=white) ![RxCocoa](https://img.shields.io/badge/RxCocoa-B7178C?style=flat-square&logo=reactivex&logoColor=white) ![RxDataSources](https://img.shields.io/badge/RxDataSources-B7178C?style=flat-square&logo=reactivex&logoColor=white) | +| **Architecture** | ![MVVM](https://img.shields.io/badge/MVVM-6DB33F?style=flat-square&logo=databricks&logoColor=white) ![Input/Output Pattern](https://img.shields.io/badge/Input%2FOutput_Pattern-6DB33F?style=flat-square&logo=databricks&logoColor=white) | +| **Networking** | ![Alamofire](https://img.shields.io/badge/Alamofire-F05138?style=flat-square&logo=swift&logoColor=white) ![Router Pattern](https://img.shields.io/badge/Router_Pattern-F05138?style=flat-square&logo=swift&logoColor=white) | +| **Database** | ![Realm](https://img.shields.io/badge/Realm-39477F?style=flat-square&logo=realm&logoColor=white) | +| **Libraries** | ![Kingfisher](https://img.shields.io/badge/Kingfisher-FFA500?style=flat-square&logo=swift&logoColor=white) ![DiffableDataSource](https://img.shields.io/badge/DiffableDataSource-147EFB?style=flat-square&logo=apple&logoColor=white) | +| **Apple Frameworks** | ![MapKit](https://img.shields.io/badge/MapKit-007AFF?style=flat-square&logo=apple&logoColor=white) ![PencilKit](https://img.shields.io/badge/PencilKit-007AFF?style=flat-square&logo=apple&logoColor=white) ![CoreLocation](https://img.shields.io/badge/CoreLocation-007AFF?style=flat-square&logo=apple&logoColor=white) ![AVFoundation](https://img.shields.io/badge/AVFoundation-007AFF?style=flat-square&logo=apple&logoColor=white) ![CoreImage](https://img.shields.io/badge/CoreImage-007AFF?style=flat-square&logo=apple&logoColor=white) ![Photos](https://img.shields.io/badge/Photos-007AFF?style=flat-square&logo=apple&logoColor=white) ![PhotosUI](https://img.shields.io/badge/PhotosUI-007AFF?style=flat-square&logo=apple&logoColor=white) ![LocalAuthentication](https://img.shields.io/badge/LocalAuthentication-007AFF?style=flat-square&logo=apple&logoColor=white) | +| **Tools** | ![Xcode](https://img.shields.io/badge/Xcode-147EFB?style=flat-square&logo=xcode&logoColor=white) ![Git](https://img.shields.io/badge/Git-F05032?style=flat-square&logo=git&logoColor=white) | +| **Testing** | ![XCTest](https://img.shields.io/badge/XCTest-6C757D?style=flat-square&logo=xcode&logoColor=white) | +| **Firebase** | ![Firebase Analytics](https://img.shields.io/badge/Analytics-FFCA28?style=flat-square&logo=firebase&logoColor=black) ![Firebase Crashlytics](https://img.shields.io/badge/Crashlytics-FFCA28?style=flat-square&logo=firebase&logoColor=black) ![Firebase Cloud Messaging](https://img.shields.io/badge/Cloud_Messaging-FFCA28?style=flat-square&logo=firebase&logoColor=black) | + +### 전체 구조 +**MVVM + Reactive Programming + Input/Output** + +- Protocol 기반 DI를 적용해 데이터 레이어 의존성 분리, 테스트 용이성 확보 +- 외부 의존성인 데이터베이스, 네트워크만 DI로 분리하여 핵심 비즈니스 로직 테스트 +- 도메인 요구사항의 잦은 변화로 인해 과도한 추상화 배제, MVVM으로 관심사 분리 + +### 데이터 관리 +**데이터베이스 설계** +- Card-Sticker 1:N 정규화 관계 설계 +- 날짜 기반 인덱스 활용하여 쿼리 최적화 +- 데이터베이스 변경사항 발생시 Observable 스트림으로 UI 실시간 동기화 + +**DTO 패턴** + +- Realm 객체의 스레드 제약을 DTO 변환으로 해결하여 안전하게 데이터 전달 +- View는 DTO만 참조하여 write 트랜잭션 충돌 방지 + +### 캐싱 + +**이미지 캐싱 전략 (Kingfisher)** + +- 메모리 캐시는 100MB 또는 100개 초과 시, 디스크 캐시 는 500MB 초과 시 LRU 방식 삭제로 용량 제한 +- 메모리 캐시는 10분 후 자동 삭제, 캐시는 디스크 7일 후 자동 삭제로 시간 제한 +- Downsampling을 활용하여 썸네일 200x200, 실사용은 뷰 크기 이미지 사용 + +## 구현 기능 + +### 갤러리 + +1| 2 | 3 | 4 +|:--:|:--:|:--:|:--:| + +#### 날짜별 보기 + +- 월별 캘린더 뷰(Custom Calendar) +- 각 날짜에 최대 4개 표시 (레이아웃 3개) +- 동적 미니/최대 레이아웃 (1개/2개/3개 지도 배치) +- 월 이동, 오늘 날짜 하이라이트 + +#### 장소별 보기 + +- MapKit 기반 지도 +- 줌 레벨에 따라 핀 클러스터링 +- 대표 이미지 표시 (점유 여때에 따라 우선순위 클러스터 정렬) +- 클러스터 개수 표시 + + + + +#### 주제별 보기 + +- Vision Framework 지능 분류 (사람/음식/식물/동물/중국어 간체) + +#### 폴더별 보기 + +- 커스텀 폴더 생성/색상/센상 +- 폴더별 카드 필터링 + +### 편집 + +| 5 | 6 | 7 | +|:--:|:--:|:--:| +| 8 | 9 | 10 | + + +#### 스티커 + +- RESTful API + offset 기반 페이지네이션 +- 드래그/핀치/회전 제스처 지원 +- 신규 스티커 추가 (사진 라이브러리 접근) +- 다중 스티커 배치 지원 +- 신규 스티커 추가 시 템플릿에서 선택 가능하도록 틀 제공 + +#### 그리기(PencilKit) + +- 자유 그리기 +- 실행 취소/재실행 기능 + +#### 필터 + +- 10가지 필터 제공 +- 실시간 프리뷰 + +#### 자료 기입 + +- 날짜 입력 (OCR 자동 추출, 디폴트 오늘) +- 메모 입력 (OCR 텍스트 Vision Framework 추출) +- 위치 검색 (MapKit 장소 검색, 현재 위치) +- 폴더 선택 +- 생체 인증 (Face ID/Touch ID, 실패 시 기기 비밀번호 사용) + + +### 카드작성 +| 11 | 12 | 13 | +|:--:|:--:|:--:| +| 14 | 15 | + + +#### 미디어 선택 + +- 시스템 카메라/앨범 +- Photo Picker (전체 라이브러리 접근) +- 권한 기반 위치 그리드 (GPS/내재 메타데이터 포함) +- Limited/Authorized 권한별 그리드 데이터 템플릿 +- 그리드 표시 후 내/외부에서 선택 가능하도록 기능 제공 + +#### 카드 정보 입력 + +- 날짜 선택 +- 메모 입력 (OCR 텍스트 Vision Framework 추출) +- 위치 검색 (MapKit 장소 검색, 현재 위치) +- 폴더 선택 +- 생체 인증 (Face ID/Touch ID 생체 인증, 실패 시 기기 비밀번호 사용) + + +### 검색 / 통계 / 설정 + +| 16 | 17 | 18 | 19 | +|:--:|:--:|:--:|:--:| + +### 실시간 검색 + +- 메모 (서브텍스트 검색) 입력, OCR 텍스트 (Vision Framework 추출) 검색 +- Masonry Layout 그리드 + +### 통계 + +- 총 카드 수 / 이번 달 카드 수 / 연속 작성 일수 (Streak) 통계 +- 막대 차트 + +### 설정 + +**일반** +- 언어 선택 (한국어/영어/일본어/중국어 간체) + +**알림** +- 서비스 소식 토픽 구독 방식 FCM Topic 구독 관리 + +**지원** +- 앱 메일을 활용한 개발자 문의 +- 기기 정보 자동 수집 +- 버전별 변경사항 릴리즈 노트