본문으로 건너뛰기

iOS 27 Now Playing 프레임워크: 재생 상태와 원격 명령 통합

iOS 27: Now Playing Framework

antongubarenko.substack.com

핵심 요약

  1. Now Playing은 미디어 유형별 콘텐츠, 재생 스냅샷, 시스템 명령을 하나의 관찰 가능한 표현으로 묶어 기존 메타데이터와 원격 제어 API를 대체한다.
  2. 앱은 MediaSession을 만들고 기본 세션으로 활성화해야 하며, 새 로컬 세션과 MPNowPlayingInfoCenter 또는 MPRemoteCommandCenter를 함께 사용하면 동작이 정의되지 않는다.
  3. RemoteMediaSessionRepresentable은 외부 기기에서 재생 중인 미디어를 표현하고, 앱이 실행되지 않을 때도 푸시 알림으로 상태를 갱신하는 통합 경로를 제공한다.

도입

iOS 27의 Now Playing 프레임워크는 iOS 5부터 사용해 온 MPNowPlayingInfoCenter와 MPRemoteCommandCenter 기반 통합을 대체한다. 앱은 재생 모델을 통해 미디어 정보와 재생 상태, 시스템 명령을 함께 제공한다. 팟캐스트 예제에서는 AVPlayer를 유지하면서 이 모델을 MediaSessionRepresentable에 연결하고, 시스템 UI에서 재생·일시 정지·탐색 명령을 처리한다.

상세 요약

기존 API에서 통합 표현으로

iOS 27의 Now Playing 프레임워크는 MPNowPlayingInfoCenter의 재생 메타데이터 게시와 MPRemoteCommandCenter의 원격 명령 처리를 대신한다. 앱은 MediaSessionRepresentable을 구현해 미디어 콘텐츠, 재생 상태, 명령을 함께 설명한다. 예제의 PodcastPlayer는 AVPlayer를 계속 사용하며, 별도의 Now Playing 상태 객체를 두지 않고 실제 재생을 소유한 모델이 시스템에도 재생 정보를 제공한다.

content는 딕셔너리 형태의 메타데이터 대신 미디어 유형에 맞는 객체를 반환한다. 팟캐스트는 PodcastContent를 사용하며, 식별자와 에피소드 제목, 프로그램 이름, 유형, 길이를 담는다. 프레임워크에는 음악, 영화, TV 프로그램, 책, 라디오, 홈 미디어용 콘텐츠 유형과 다른 범주에 해당하지 않을 때 사용할 GenericContent도 있다.

재생 상태와 시스템 명령

playbackSnapshot은 재생 상태, 경과 시간, 그 값을 기록한 시점을 전달한다. 예제는 AVPlayer의 주기적 시간 관찰자로 0.5초마다 elapsedTime을 갱신하고, 스냅샷의 시점에는 .now를 사용한다. 시스템은 매초 새 진행 값을 받지 않아도 재생이 계속되는 동안 진행 상태를 계산할 수 있다.

commands에는 재생, 일시 정지, 15초 뒤로 이동, 30초 앞으로 이동, 특정 위치로 이동하는 동작을 클로저로 선언한다. 잠금 화면, 제어 센터, CarPlay 등 지원되는 시스템 화면에서 사용자가 명령을 실행하면 해당 클로저가 호출된다. enabled(_:)를 이용해 재생 상태에 따라 명령을 사용할 수 없게 만들 수도 있다. 예제에서는 이동 위치를 에피소드 길이의 범위 안으로 제한한다.

세션 생성과 마이그레이션

MediaSessionRepresentable을 구현하는 것만으로는 충분하지 않다. 앱은 MediaSession을 생성해 보관하고 requestToBecomeApplicationPrimary()를 호출해 애플리케이션의 기본 세션으로 요청한다. 앱은 음악과 팟캐스트처럼 여러 세션을 가질 수 있지만, 애플리케이션 기본 세션은 한 번에 하나다. requestToBecomeSystemPrimary()는 시스템 활성 세션이 되도록 요청하며, 앱이 포그라운드에 있을 때 호출해야 한다. 세션을 해제하면 시스템에서도 제거된다.

기존 앱은 실제 재생 엔진을 유지하고 시스템 연동 계층을 교체할 수 있다. 다만 Apple은 새 로컬 Now Playing 세션과 MPNowPlayingInfoCenter, MPRemoteCommandCenter를 함께 사용하는 것을 경고한다. 함께 사용할 경우 동작이 정의되지 않으므로, 기존 API와 새 API로 상태를 나눠 게시하는 점진적 혼용 방식은 피해야 한다.

외부 기기 재생과 백그라운드 설정

RemoteMediaSessionRepresentable은 외부 스피커, 스트리밍 장치, TV에서 실제 재생 중인 미디어를 표현한다. 통합은 앱 확장에 두며, 메인 앱이 실행되지 않은 때에도 푸시 알림으로 원격 상태를 갱신할 수 있다. 시스템 UI의 명령은 확장을 거쳐 서비스나 기기로 전달된다. 따라서 외부 장치를 제어하는 앱은 iPhone에서 재생되지 않는 오디오도 잠금 화면과 제어 센터에 나타낼 수 있다.

기기 잠금 또는 백그라운드 상태에서도 오디오를 재생하려면 Xcode의 Signing & Capabilities에서 Background Modes의 Audio, AirPlay, and Picture in Picture를 활성화해야 한다. 이 설정은 UIBackgroundModes에 audio 값을 추가한다. AVAudioSession의 카테고리를 .playback으로 설정하는 것만으로는 백그라운드 오디오가 활성화되지 않는다.

결론

새 API의 핵심은 메타데이터와 명령을 별도로 관리하는 대신, 재생을 소유한 모델을 시스템이 관찰하게 하는 데 있다. 마이그레이션 시 재생 엔진은 그대로 둘 수 있지만, 새 로컬 세션과 기존 Media Player API를 혼용해서는 안 된다. 외부 재생 장치를 제어하는 앱은 원격 세션을 사용할 수 있으며, 백그라운드 오디오 재생에는 Xcode의 Background Modes 설정도 별도로 필요하다.