[내일배움캠프 11주차 (03/19)]

yeseul jang·2026년 3월 19일

내일배움캠프

목록 보기
24/32

📱 iTunes Search App

iTunes API를 활용하여 음악, 앨범, 팟캐스트를 검색하고 상세 정보를 확인할 수 있는 iOS 앱입니다.
음악에 관해서는 미리듣기가 재생됩니다.
RxSwift와 MVVM 패턴을 기반으로 비동기 데이터 흐름을 관리하고, 효율적인 UI 업데이트를 구현했습니다.

홈화면/디테일화면검색화면/디테일화면
수정본홈수정본검색

🛠 기술 스택

  • UIKit
  • RxSwift / RxCocoa
  • MVVM (Input / Output 패턴)
  • Diffable DataSource
  • SnapKit
  • Kingfisher (이미지 로딩 및 캐싱)
  • AVPlayer (iTunes 미리듣기 재생)

📂 아키텍처

MVVM + Input / Output

  • ViewModel에서 Input → Output 변환
  • ViewController는 Output을 바인딩하여 UI 업데이트

프로토콜

protocol ViewModelType {
    associatedtype Input
    associatedtype Output
    func transform(input: Input) -> Output
}

구현 예시

struct Input {
    let viewDidLoad: Observable<Void>
}

struct Output {
    let sections: Driver<[HomeSectionModel]>
    let isLoading: Driver<Bool>
    let errorMessage: Signal<String>
}

목적

  • 비즈니스 로직과 UI 분리
  • 테스트 가능성 증가
  • 데이터 흐름 단방향 유지

🔍 주요 기능

1. 홈 화면

  • iTunes API를 통해 음악 데이터 로드
  • Diffable DataSource로 섹션 구성
  • 로딩 상태 및 에러 처리

2. 검색 기능

  • 검색어 입력 시 새로운 화면에서 결과 표시
  • song / album / podcast 검색 지원
  • RxSwift로 입력 이벤트 스트림 처리
  • 로딩 상태 및 에러 처리

3. 상세 화면

  • 선택한 아이템의 상세 정보 표시
  • 미리듣기가 있는 경우 영상 재생 (AVPlayer 활용)

4. 네트워크 구조

  • NetworkService → API 요청 담당
  • ITunesEndpoint → API URL 구성
  • ITunesResponse → 응답 모델

🔹 특징

  • async/await 기반에서 Rx로 변환하여 사용
  • ViewModel에서 비동기 처리

💡 고민 및 개선 포인트

📖 상세화면 고민했던 점

1. item을 어떻게 스트림으로 전단할 것인가 Observable.just(item) vs input.viewDidLoad.map { item }

  • 상세 화면에서 전달받은 item은 이미 생성 시점에 존재하는 값이기 때문에, 단순히 값만 전달하는 목적이라면 Observable.just(item)으로도 구현할 수 있음
Observable.just(item)
  • 하지만 이 방식은 구독되는 순간 즉시 값이 방출됨
  • 원래 의도했었던 View가 로드되면 item을 전달하려는 흐름(View의 생명주기)과는 관련이 없게 됨

1-1. 해결방안

input.viewDidLoad
    .map { _ in self.item }
  • viewDidLoad 이벤트가 발생했을 때를 기준으로 item을 방출하도록 변경함

  • 원래 의도대로 화면이 준비된 시점에 맞춰 데이터를 전달한다는 흐름을 명확하게 표현할 수 있음

  • 이 프로젝트는 MVVM + Input / Output 패턴을 기반으로 구성되어 있기 때문에 단순한 값 전달보다도 이벤트를 기준으로 데이터 흐름을 관리하는 구조를 유지하는 것이 더 중요하다고 판단해서 수정함

1-2. 정리

  • Observable.just(item)
    → 구독 시 즉시 값 방출
  • input.viewDidLoad.map { item }
    viewDidLoad 이벤트 시점에 값 방출
  • 결과적으로 두 방식 모두 기능적으로 큰 차이는 없이 구현은 가능하지만,이번 프로젝트에서는 View 생명주기와 데이터 흐름을 일치시키고, Input Output 구조를 유지하기 위해 viewDidLoad를 트리거로 사용하는 방식으로 결정함

🚀 추가해 보면 좋을 사항

  • 무한 스크롤 (pagination) 구현해보기
  • 검색 결과 캐싱
  • 관련 뮤직비디오 재생

추가 기능) 뮤직 비디오 재생 기능 구현

디테일 화면 뮤비 재생
  • 관련된 뮤비가 있을 경우에 재생됨
  • 없는 경우에는 그냥 전과 같이 정사각형 앨범 아트가 보여지게 됨
profile
iOS 개발

0개의 댓글