Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 

Repository files navigation

무비박스

기억에 남는 영화를 찾아 나만의 코멘트를 남기고, 영화 카드로 보관할 수 있는 영화 기록 앱

appstore
무비박스 화면 영화 검색 화면 영화 상세 정보 화면 영화 카드 제작 화면
Simulator Screen Recording - iPhone 15 Pro - 2024-10-01 at 01 09 00 Simulator Screen Recording - iPhone 15 Pro - 2024-10-07 at 03 57 40 Simulator Screen Recording - iPhone 15 Pro - 2024-10-07 at 03 59 38 Simulator Screen Recording - iPhone 15 Pro - 2024-10-07 at 04 26 20

🗄️ 프로젝트 정보

  • 기간 : 2024.09.19 ~ 2024.09.30 (약 1주)

  • 개발 인원 : iOS 1명

  • 지원 버전:

  • 기술 스택 및 라이브러리 :

    • UI: SwiftUI Shufflelt SwiftUIVisualEffects Cosmos YouTubePlayerKit
    • Reactive: Combine
    • Network: Moya
    • 로컬 저장소: Realm
    • DI Container: Swinject
  • 프로젝트 주요 기능

    • 영화 카드 컬렉션 기능

      • 카드 덱과 카드 앞뒷면 구현을 통한 직관적인 카드 UI/UX 제공
      • 별점 / 코멘트 기능
    • 영화 검색 기능

      • 주간 인기 영화 목록 조회
      • 영화 키워드 검색
        • 무한 스크롤 기능
    • 영화 상세 정보 조회 기능

      • 영화 기본 정보 제공
      • 포토 갤러리 / 동영상 / 비슷한 영화 / 추천 영화 컨텐츠 제공

🧰 프로젝트 주요 기술 사항

이미지 캐시 전략 및 구현


이미지 캐시 전략



  • 영화 검색 결과에 대한 이미지는 사용자가 빠르게 소비하는 단기적인 데이터이므로 NSCache를 이용한 메모리 캐시만 적용

  • 주간 인기 영화에 대한 이미지는 주 단위로 바뀌는 장기적인 데이터이므로 FileManager를 이용한 Etag 기반 디스크 캐시만 적용

    • 20개의 데이터 중 평균적으로 3-4개의 데이터만 업데이트 되기에 주 단위로 모든 데이터를 제거하는 것이 아니라 변동된 데이터만 삽입/삭제
  • 영화 상세 정보에 대한 이미지는 사용자가 관람할 영화를 고르기 위해 해당 화면에 접근 후 앱을 종료한 뒤 영화 관람 후 다시 앱을 실행하여 영화 카드를 제작하는 시나리오를 고려하여 메모리 캐시와 Etag 기반 디스크 캐시를 혼합하여 적용

    • 디스크 캐시 히트율을 높히기 위해 LRU와 LFU를 혼합한 디스크 캐시 적용


LRU와 LFU 알고리즘을 혼합한 디스크 캐시 구현





  • LRU 알고리즘을 구현 시 접근 시간에 대한 max 연산의 O(N) 시간복잡도를 이중 연결 리스트를 사용하여 O(1)로 개선
  • 메인 스레드에서의 I/O Bound 문제를 해결하고 I/O 작업 중 발생할 수 있는 Data Race를 방지하기 위해, Custom Serial Queue를 활용한 Non-Blocking I/O 적용


이미지 리사이징을 활용한 메모리 최적화


스크린샷 2024-10-05 오후 4 11 15 스크린샷 2024-10-05 오후 4 12 19

  • 원본 이미지를 단순히 resizable().frame(width:height:)으로 크기를 조절할 시 원본 이미지를 그대로 렌더링하므로 불필요하게 메모리가 많이 사용됨
  • UIGraphicsImageRenderer를 사용해서 이미지 뷰가 필요로 하는 크기에 맞추어 리사이징하여 필요한 만큼만 픽셀 정보를 메모리에 로드시켜 메모리를 절약


DI Container를 활용한 Clean Architecture + MVVM

영화 상세 정보 조회 기능에서의 Clean Architecture 활용 예시


Data 계층



  • DataSource 객체

    • 내/외부 데이터소스 작업 객체
    • NetworkManger와 같은 싱글톤 객체를 사용하기보다 기능 관련 리소스 단위를 더 명확하게 표현하고자 도입
  • DefaultMovieContentRepository

    • async let을 사용하여 여러 개의 비동기 컨텍스트를 병렬적으로 처리
    • DataSource의 반환값을 Result 타입으로 할 경우 반복적인 switch문에 의해 불필요하게 코드 수가 늘어나는 것을 방지하기 위해 async throw와 try? 조합 사용

Domain 계층



  • 내/외부 Repository를 조합하여 완전한 Entity 데이터 생성
  • ViewModel의 책임을 View와의 데이터 바인딩 역할로 제한하기 위해 UseCase 도입


Presentation 계층



  • Input으로는 PassThroughSubject, Output은 @Published를 활용하여 View와 데이터 바인딩
  • Entity를 Presentation Model로 가공하여 View가 직접 Entity를 가공하지 않게 함

DI Container



  • DI Container 도입 이유

    • ViewModel 객체를 하나 만들기 위해서 일일히 UseCase, Repository, DataSource 구현체를 생성하여 주입시키기 번거로움
    • 영화 상세 정보 화면의 경우 다른 영화 상세 정보 화면으로 넘어갈 수 있어 동일한 Resolve 체인이 반복적으로 생성될 수 있기 때문에 각각의 구현체 인스턴스를 단일로 유지하여 메모리적 이점을 가져가고자 하였음
  • DI Container 활용 방법

    • MovieContentViewModel에서 UseCase를 주입받는 코드를 @Injected 프로퍼티 래퍼를 통해 추상화
    • 대부분의 구현체들은 단일로 유지되게 설정하였지만, 영화 검색 결과 화면에 사용되는 DataSource 구현체의 경우 Pagination 관련 상태값을 가지고 있기 때문에 매번 새로운 인스턴스를 생성되게 설정

About

이미지 캐시 구현(ETag, LRU + LFU 혼합 알고리즘) / Clean-Architecture + MVVM

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages