- Apple Itunes API를 사용하여, 앱스토어 내의 앱을 검색, 그리고 상세화면까지 보여줍니다.
- 진행기간: 2023.05 - 2023.06
- 개발환경
- Swift
- Deployment Target: 15.0
- Architecture: MVVM-C
- 프레임워크: Combine
- 코드로 UI를 구현했습니다.
- MockURLSession을 활용하여 네트워크 테스트 및 테스트코드를 작성했습니다.
- 실제 앱스토어의 검색화면을 구현했습니다.
- 검색화면은 TableView와 SearchController로 구성되어 있습니다.
- 앱 평점을 별이미지로 나타냈고, 단위를 환산하여 보여줍니다.
- 상세화면은 CustomView, 가로 ScrollView, TextView, CollectionView, TableView로 구성되어있습니다.
- 상세화면에서는 각 앱의 최소 구동 OS를 보여줍니다.
- 카테고리 항목별 이미지를 배치하여 손쉬운 이해를 돕습니다.
- 가로 ScrollView를 활용하여, 평점, 연령, 카테고리, 언어 등 주요 정보를 보여줍니다.
- CollectionView를 활용하여, 미리보기 이미지를 보여줍니다.
- TableView를 활용하여, 앱의 정보를 보여줍니다.
- 이미지 Cache를 구현하였습니다.
- 다크/라이트 모드에 대응합니다.
Part 1 - 전반적인 부분
Coordinator 패턴을 적용하여 의존성 주입을 관리하고, 화면전환 역할을 하며, View끼리 의존관계를 낮추려고 했습니다. 이를 위해 navigationController를 생성자 주입 방식으로 하위 Coordinator에게 전달합니다.
검색 -> 상세 순으로 연결되므로 각 상위 Coordinator의 childCoordinator에 하위 Coordinator를 추가했습니다.
Apple의 First-Party 프레임워크인 컴바인을 사용했습니다. 비동기 작업을 처리하였으며, 서버에서 받아온 데이터를 Publisher타입으로 반환하고, ViewModel 및 ViewController를 Binding 하여 화면에 나타내도록 구현하였습니다. 또한 사용자 이벤트 처리를 위해서 ViewController에서 PassthroughSubject를 활용했습니다.
Apple의 iTunes Search API를 활용하였습니다. API는 열거형으로 관리하는 경우, 새로운 case를 생성할때마다 관련된 switch문을 매번 수정해야하는 번거로움이 존재합니다. 이를 구조체 타입으로 만들고, Protocol을 활용함으로써 코드유지 보수가 용이하며, 문제 발생 시 빠르게 해결할 수 있는 장점이 존재합니다.
올바르게 작동하는지 테스트를 위해, 디코딩테스트, MockURLSession 테스트, 실제 네트워크 테스트를 진행했습니다.
MockURLSession은 다음과 같은 이유로 작성했습니다.
- 실제 서버와 통신할 경우 테스트의 속도가 느려짐
- 인터넷 연결상태에 따라 테스트 결과가 달라지므로 테스트 신뢰도가 떨어짐
Part 2 - 검색 화면 부분
검색창에 터치를 하게 되면, 검색창이 상단으로 올라가는 애니메이션을 위해 UISearchController로 구현하였습니다.
앱의 썸네일을 매번 서버로부터 요청받아 화면에 띄우는 것은 비효율적이라고 생각을 하여, NSCache를 이용하여 메모리 캐시를 도입했습니다. 메모리에 이미지가 존재한다면 이미지를 반환해주고, 존재하지 않는다면 서버에 요청해 이미지를 받아옵니다. 요청 시 이미지를 성공적으로 받아왔다면 캐시에 저장하여 다음번에 이미지를 사용하는 경우 캐시에서 이미지를 받아올 수 있도록 했습니다.
앱 검색 시 나타나는 별점을 StarImageView를 통해 구현했습니다. 평점 데이터를 받아 필요한 개수만큼의 별을 생성하며 StackView에 추가하였습니다. 소수부의 자리가 0.5를 넘는다면 별이 반개가 표시되며, 넘지않으면 빈 별이 표시되도록 구현했습니다.
Part 3 - 상세 화면 부분
앱스토어의 상세화면을 다양한 뷰를 이용하여 ScrollView + StackView 안에 담아내었습니다.
순서대로 CustomView - ScrollView - Label - TextView - Label - CollectionView - TextView - Label - TableView
입니다.
Detail화면을 5번 띄운 후의 모습입니다. DetailViewController가 메모리에서 해제되었음에도 불구하고, DetailCoordinator가 5개가 남아있는 모습입니다. DetailCoordinator의 할 일이 사라졌으므로, 메모리 누수를 방지하기 위해 viewController의 deinit시 같이 제거해주었습니다.
(수정 전)

(수정 후)
