# Album App
> 프로젝트 기간 2024.01.24 ~ 2024.01.28 (5일) <br>
개발자 : [iOS 개발자 김태현](https://github.com/derrickkim0109)
URL : [ReadMe Link](https://hackmd.io/wqr2hZDbQfevqR7qo5ftSA)
# 📋 목차
- [🔎 프로젝트 소개](#-프로젝트-소개)
- [📺 프로젝트 실행화면](#-프로젝트-실행화면)
- [🗂 App 구조](#-app-구조)
- [⁇ 고민한 점](#-고민한-점)
- [! 아쉬운 점](#-아쉬운-점)
- [📋 과제요구사항관리](#-과제요구사항관리)
## 🔎 프로젝트 소개
> 카메라 기능, 앨범 별 사진리스트, 사진 자르기, 회전을 통해 이미지를 수정할 수 있는 앱입니다.
## 📺 프로젝트 실행화면
### Page - 1 & 2
|메인 화면 - 사진없을 경우|메인 화면 - 사진있는 경우|앨범 권한|
|--|--|--|
|<img src="https://hackmd.io/_uploads/BJgGV4Qqp.png" width="250">|<img src="https://hackmd.io/_uploads/SyxlGE4Qca.png" width="250">|<img src="https://hackmd.io/_uploads/HkAMTVm5T.png" width="250">|
### Page - 2
|앨범 권한 허용|사진 선택|앨범 제한된 권한 허용|앨범 권한 허용 안함|
|--|--|--|--|
|<img src="https://hackmd.io/_uploads/B1-lzVE7q6.png" width="250">|<img src="https://hackmd.io/_uploads/Bkm-HNQ96.png" width="250">|<img src="https://hackmd.io/_uploads/r1xlzNVQqp.png" width="250">|<img src="https://hackmd.io/_uploads/S1eef4NQqp.png" width="250">|
|카메라 권한|카메라 권한 허용|카메라 권한 허용 안함|
|--|--|--|
|<img src="https://hackmd.io/_uploads/ryn9pV75p.png" width="250">|<img src="https://hackmd.io/_uploads/SkRCTVQ9a.png" width="250">|<img src="https://hackmd.io/_uploads/H1h96Em5T.png" width="250">|
### Page - 3
|이미지 편집 화면|이미지 자르기 화면|이미지 회전|
|--|--|--|
|<img src="https://hackmd.io/_uploads/HkEQeHQ96.png" width="250">|<img src="https://hackmd.io/_uploads/BkoBWjmcT.png" width="250">|<img src="https://hackmd.io/_uploads/B1UNsOQ96.gif" width="250">|
|회전된 이미지 저장|잘라진 이미지 저장|
|--|--|
|<img src="https://hackmd.io/_uploads/HJEd2dQqp.png" width="250">|<img src="https://hackmd.io/_uploads/HyNV4jX5p.jpg" width="250">|
---
## 🗂 App 구조
### 기술스택
- UIKit
- Combine
- MVVM-C
- Unit Test
### Version
- **Xcode 15.2**
- **iOS Simulator 17.0.1**
- **iOS Deployment Target 15.0**
- **Minimum Deployment 15.0**
### Commit Convention
- Karma
## ⁇ 고민한 점
### Coordinator Pattern
> 이번 프로젝트의 화면 전환에서 조금 생소하게 생각했던 점은 Present된 뷰에서 다시 pushViewController가 되어야 한다는 점입니다.
> - 화면 Flow는 `당근의 사진 앨범 Flow`, `Apple 사진 앨범 Flow`를 참고 했습니다.<br>
<img width="200" height="500" alt="스크린샷 2023-11-11 13 15 03" src="https://hackmd.io/_uploads/SJq-BtN9p.png">
프로젝트에서 화면 전환의 복잡성을 고려하여 Coordinator 패턴을 도입했습니다. 이 패턴은 화면 전환의 Flow를 명확하게 정의하고, 각각의 화면 전환 로직을 독립적으로 관리할 수 있게 해줍니다. 또한, AViewController에서 BViewController로 데이터를 전달하고, 다시 AViewController로 돌아올 때의 상황을 쉽게 다룰 수 있다는 점입니다.
### 🗺️ DI Container
DI Container를 도입하여 ViewController의 생성과 의존성을 관리했습니다. 이를 통해 각 뷰 컨트롤러에서 필요한 Repository를 명확하게 파악하고 주입함으로써 코드의 가독성을 높일 수 있습니다. 또한, 테스트 용이성을 증가시키고 코드의 유연성을 높여줄 수 있습니다.
DI를 적용하지 않을 경우, 특정 Repository가 ViewController혹은 ViewModel 내에 생성되어 Mock 객체를 만들어 테스트를 진행할 수 없다는 점, 내부에서 저수준 모듈에 종속성을 가져 변경, 확장에 유연하지 못하는 코드가 될 수 있다는 점이 있습니다.
종합적으로, Coordinator 패턴과 DI Container의 도입으로 프로젝트의 구조와 유지보수성을 향상시킬 수 있었다고 생각합니다.
### 재사용을 위한 코드
> 재사용하기 위한 객체가 무엇인지 고민했습니다.
특정 뷰를 구현할 때, 재사용을 위한 코드와 역할 상 불필요한 기능이 있을 것으로 판단되는 뷰를 구분했습니다. 또한, 의존성 역전원리를 통해 각 Repository들을 추상화 된 객체에 의존하도록 설계했습니다.
## 아쉬운 점
- Code Coverage 50%이상 채우지 못한점
- Rotation, Crop View 고도화 및 기능 파악
- setNeedsLayout vs layoutIfNeeded
**Code Coverage 50%이상 채우지 못한점**
> Unit Test를 사용하여 Code Coverage 50%를 채우지 못했습니다. 테스트의 용이성에 좋은 방식이 무엇인지 학습해봤으나, 실제 프로젝트에서 제대로 고려하여 테스트 코드를 작성하지 못해 발생한 문제점이라고 생각합니다. 조금 더 테스트를 진행해야 하는 부분이 무엇인지 고민했어야지만 못한 점이 아쉬움으로 남습니다.
**Rotation, Crop View 고도화 및 기능 파악**
> 참고한 오픈소스의 설명에 앞서 해당 오픈소스를 찾게 된 계기에 대해 설명드리겠습니다. <br>
Apple의 앨범에 있는 크롭 기능을 참고하여 Documentation에서 cropping(to:)란 메서드에 대해 알게 되었습니다. 해당 메서드를 어떻게 사용하면 좋을 지 참고할 프로젝트를 찾던 중 아래의 프로젝트를 알게 되었습니다.
[LyEditImageView](https://github.com/Thanatos-L/LyEditImageView) 오픈소스를 참고하여 이미지의 Rotation, Crop 기능을 구현했습니다.
현재 프로젝트에는 LyEditImageView의 각 객체 분리, view 초기화, 프로퍼티 설정들을 정리한 상태로 구현했습니다. 아쉬운 점은 해당 기능을 정확하게 파악하지 못하고 적용했다는 점입니다.
**setNeedsLayout vs layoutIfNeeded**
> 깊게 생각하지 못하고 코드를 작성한 부분이 아쉬웠습니다.
즉시 뷰를 갱신하는지, update cycle에 갱신하는지에 대한 고려를 하지 못했습니다.
두 메서드에 대해 조금 더 명확하게 알기 위해 학습해봤습니다. [setNeedsLayout vs layoutIfNeeded](https://hackmd.io/ZTOlAUGaR-2rTxKnvbX0zw)
## 📋 일정관리
<img width="1225" alt="스크린샷 2023-11-11 13 14 44" src="https://hackmd.io/_uploads/SJFQp379T.png">
> GitHub issue 이미지
- 구현할 feature, test에 대한 내용을 Github의 issues에 정리했습니다. 진행할 업무를 정리하고, 우선순위를 정하기 위함입니다.
- 진행하는 issue들 별로 Todo, In Progress, Done을 통해 Feature History를 관리했습니다.
<img width="1227" alt="스크린샷 2023-11-11 13 15 03" src="https://hackmd.io/_uploads/SJfUTnXqa.png">
> GitHub branch 이미지
- Branch를 issue별로 분기 처리하여 관리하였습니다.
**Git Flow**
각 Branch의 구현 후, develop 브랜치에 Merge하고 최종적으로 main Branch에 Merge하는 방식으로 과제를 수행하였습니다.