스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
배경 자산 소개
배경 자산 프레임워크를 사용하여 CDN에서 대용량 파일을 직접 다운로드하고 앱과 게임의 초기 실행 경험을 향상하는 방법을 확인하세요. 초기 앱 설치 시, 앱 업데이트 시, 그리고 앱을 사용하는 동안 주기적으로 배경 다운로드를 예약하는 방법을 보여드립니다. 또한 사용자가 원하는 콘텐츠를 원하는 시기에 확보할 수 있도록 다운로드 예약을 관리하는 방법을 알아보겠습니다.
리소스
관련 비디오
WWDC23
Tech Talks
WWDC21
-
다운로드
♪ 부드러운 힙합 반주 ♪ ♪ 안녕하세요, Jared입니다 이 애플의 소프트웨어 기술자죠 오늘 얘기할 새 프레임워크는 올해 iOS와 iPadOS macOS에 소개됩니다 백그라운드 에셋이란 새 프레임워크로 우리 모두가 알고 아끼는 앱의 사용자 경험을 풍성하게 해 줄 겁니다 여러분이 개발하는 앱에는 더 중요하죠 우선 새 백그라운드 에셋 프레임워크를 소개해 드리겠습니다 그리고 새 프레임워크를 여러분 앱에 어떻게 쓰는지 보여 드리죠 그다음엔 익스텐션과 새 기능을 간단히 요약해 드리겠습니다 그리고 최고의 연습과 배운 걸 다 복습하면서 마무리하고요 시작하기 전에 여기서 해결하려는 걸 얘기하죠 사실 기다리는 건 재미없어요 우리 프로그램을 쓰는 분들께 기다리라고 요구하면 더 짜증 나고 우리 뜻대로 앱을 체험하게 할 수 없습니다 예를 들어 완벽한 앱을 찾고자 얼마나 자주 App Store를 한없이 둘러보세요? 마침내 그런 걸 찾으면 참 완벽해 보이죠 GET 버튼을 탭하면 시간이 갈수록 여러분의 기대감이 커집니다 그러다 곧 깨닫습니다 네트워크 연결과 앱 용량에 따라 앱이 다운로드되길 기다려야 한다는 걸요 몇 초 기다리고 나면 여러분의 전화기를 내려놓고서 커피를 들고 좋아하는 책을 읽을 겁니다 마음 챙김 수련과 인내를 터득하는 이점을 다룬 내용이겠죠 그렇게 몇 시간이 지나 마침내 전화기를 집어 들면 기대감이 커지고 온종일 기다린 완벽한 앱을 쓰려고 준비합니다 그 앱을 시작하는 순간 이런 말이 나오죠 다운로드가 남았다고요 당황스럽죠 종일 전화를 안 썼는데 이 앱이 왜 더 기다리게 할까요? 앱이 설치되면 자동으로 콘텐츠를 내려받게 할 순 없나요? 인터넷 속도가 느린 분이라면 짜증 나서 앱을 닫고 삭제할지도 모릅니다 사실 이런 경험을 원하는 사람은 없습니다 여러분 잘못이 아니니 우리가 그 경험을 개선할 수 있다고 믿고 올해 '백그라운드 에셋'를 자랑스럽게 소개하죠 앱 사용자 경험을 풍성하게 해 주게끔 개발한 프레임워크라서 앱을 시작하는 순간 경이로운 첫인상을 선사합니다 기존 워크플로와 탄력적으로 융화되게 설계했습니다 복잡한 에셋 관리 시스템은 이미 많이 개발됐으니 개발돼 있는 해결책에 쉽게 들어맞는 새 프레임워크였으면 했죠 App Store에 추가적으로 제출하지 않아도 업데이트된 콘텐츠를 앱에 적용하고 싶은 마음도 압니다 앱을 받은 후에 추가적인 콘텐츠가 필요한 게임이나 앱은 드물지 않아요 아트 텍스처 갱신과 게임 레벨 데이터의 버그 픽스 같은 거죠 백그라운드 에셋은 앱 수명 주기와 무관하게 에셋을 예정하고 업데이트할 수 있습니다 처음 앱을 시작하거나 야간 업데이트를 하기 전에 에셋이 존재하는 게 중요하다고 봅니다 그래서 앱이 시작될 무렵엔 콘텐츠가 존재하게 하는 방식을 개발했죠 마지막으로 프레임워크가 쓰기 쉬울수록 앱에서 사용하게 더 권장할 수 있습니다 대용량 에셋을 미리 내려받아야 할 때마다 백그라운드 에셋을 쓰셨으면 합니다 그러면 앱 대기 시간을 최소화하고 콘텐츠를 쓰기 전에 진행 바를 보여 줄 수 있죠 이런 문제 해결에 새 프레임워크가 어떻게 유용한지 궁금하세요? 확장성을 최대한 갖추기 위해서 백그라운드 콘텐츠 다운로드용 앱 익스텐션을 개발했죠 우리 플랫폼의 다른 익스텐션이 쓰고 있는 강력한 앱 확장 기술을 갖춘 새 익스텐션입니다 그래서 앱 수명 주기와 무관하게 코드를 실행할 수 있어요 예를 들어 처음 앱을 설치해 시작하기 전이라도 늘 실행되는 익스텐션이죠 백그라운드에서 앱이 자동 업데이트될 때도 익스텐션이 실행됩니다 앱이 업데이트된 이후 사용자가 앱을 열기 전에 콘텐츠를 예정하고 내려받는 데 유용합니다 마지막으로 백그라운드에서 주기적으로 실행돼 업데이트된 에셋을 확인하고 주기적으로 예정할 수 있게 해 주죠 주의해야 할 점은 익스텐션 런타임이 짧으니 익스텐션으로 신속히 모든 작업을 예정해야 하는 거죠 다운로드가 빨리 예정 안 되면 시스템이 익스텐션을 종료시킬 수도 있죠 앱 사용률에 따라 익스텐션이 주기적으로 실행되는 빈도가 주는 것도 중요한 점이니 알아 두세요 앱을 자주 쓰지 않으면 익스텐션의 런타임 빈도가 감소합니다 새 백그라운드 에셋 프레임워크 개요였는데 앱이 시작될 때 에셋을 쓸 수 있게 해 주는 도구를 제공합니다 설치되거나 갱신될 때마다 사용자가 앱을 시작하기 전에 익스텐션이 이렇게 실행됩니다 이제 여러분 프로젝트에 이 프레임워크를 써서 시작하는 걸 살펴보겠습니다 프레임워크의 다운로드 매니저는 백그라운드 에셋 시스템 서비스와 소통하는 주요 도구입니다 전체적인 앱에 쓰는 싱글톤 객체 매니저죠 이 매니저로 포어그라운드나 백그라운드 에셋의 다운로드를 예정합니다 실행 중인 다운로드도 검색할 수 있는데 앱을 시작하기도 전에 다운로드가 개시될 수도 있죠 다운로드가 취소되거나요 예정된 다운로드거나 내려받는 중인데 원래 요청했던 에셋이 필요 없어질 때 유용한 기능이죠 앱과 익스텐션 사이의 전용 접속을 관리할 수 있는 동기화 방식도 소개합니다 익스텐션과 앱이 동시에 예정하거나 기존의 다운로드를 변경하지 않게요 나중에 여러분께 예시를 보여 드리겠습니다 백그라운드 에셋을 얼마나 쉽게 쓰기 시작하는지 살펴보죠 우선 API의 기본부터 소개해 드리겠습니다 그리고 나중에 앱 확장 프로그램으로 어떻게 다 접목하는지 보여드리죠 시작하려면 백그라운드 에셋 프레임워크 모듈을 불러오세요 그러면 원격 에셋이 있는 장소롤 가리키는 URL을 정의하기 쉬워집니다 그다음엔 익스텐션과 앱 모두가 구성 요소인 앱 그룹 컨테이너를 정의하죠 앱과 익스텐션을 한 그룹에 두면 다운로드 도중과 완료 후에 에셋을 관리할 수 있습니다 앱 그룹에 익숙하지 않다면 Xcode 14의 서명과 기능 부분에서 쉽게 추가할 수 있죠 두 개 이상의 응용 프로그램이 같은 리소스에 접속하는 강력한 기능인데 이 경우엔 여러분 앱과 익스텐션이죠 그다음엔 다운로드 객체를 만듭니다 백그라운드 에셋 프레임워크 설계상 다양한 다운로드 객체를 지원할 수 있죠 하지만 이 예시에선 가장 흔한 BAURLDownload에 초점을 맞춥니다 이니셜라이저가 URL과 앱 그룹 식별자를 즉시 받아들이는 걸 볼 수 있죠 뭘 다운로드하고 결과 파일이 어디로 갈지 시스템에 알리는 정보입니다 이 정보는 식별자도 채택하죠 이 식별자로 앱과 익스텐션 안에서 다중 개시되는 다운로드를 추적할 수 있습니다 엔진은 같은 식별자로 다운로드를 하나 이상 예정하게 허가하지 않죠 그러니 고유한 식별자로 만들어야 합니다 그리고 BADownloaderManager에 공유 객체를 참조합니다 다운로드 매니저는 백그라운드 에셋의 단일 인터페이스로 다운로드를 관찰하고 취소하며 예정하게 해 줍니다 BADownloadManager Delegate에 따르는 대리자에게 약한 참조를 넘기는 게 다음 차례입니다 곧 더 살펴보겠지만 지금은 예정된 다운로드에 대한 메시지를 받는다는 걸 알아 두는 게 중요하죠 이제 남은 일은 다운로드 매니저에 다운로드 예정을 요청하는 거죠 어떤 이유로든 다운로드를 예정 못 하면 에러가 발생합니다 백그라운드 다운로드 예정과 더불어 API에 포어그라운드 다운로드도 지원하죠 포어그라운드 실행은 우선권이 늘 뿐 아니라 즉시 다운로드를 개시하게끔 해 줍니다 URLSession 내부의 디폴트 세션 설정을 쓰는 것과 비슷하죠 이렇게 API를 지원하면 앱이 백그라운드 익스텐션이 포어그라운드로 예정한 다운로드를 촉진하죠 명심하실 게 있는데 익스텐션 안에선 포어그라운드 다운로드가 안 됩니다 앱에서만 개시할 수 있거든요 익스텐션은 UI를 제공하지 않고 사용자가 실행되는지 모르면 익스텐션이 백그라운드에서만 다운로드를 예정하죠 백그라운드 다운로드를 앱이 포어그라운드로 촉진하려면 매니저에서 활성화된 다운로드 목록을 불러와 쉽게 이 작업을 할 수 있죠 반송된 목록엔 현재 예정된 다운로드가 다 들어가는데 스케줄러에서 실행되거나 대기하는 다운로드도 포함되죠 이젠 startForeground Download를 호출해 앱이 촉진 과정을 시작할 수 있습니다 이미 포어그라운드 다운로드면 이 메서드를 불러도 사실 하는 게 없죠 하지만 백그라운드 다운로드였다면 일단 중지됐다 포어그라운드에서 재개됩니다 다시 다운로드받는 시점까지 이미 다운받은 콘텐츠를 요청하지 않고요 백그라운드 에셋을 써서 백그라운드에서 포어그라운드로 예정된 다운로드 촉진이 얼마나 쉬운지 효과적으로 간단히 보여 주죠 진짜 이렇게 간단합니다 다운로드 매니저는 백그라운드 다운로드를 예정하고 모니터하는 주요 인터페이스죠 이런 다운로드 객체를 시스템이 처리하니 대리자 객체에서 메시지를 받는데 이 대리자를 살펴보죠 대리자는 익스텐션이나 앱이 예정한 다운로드 메시지를 전부 받습니다 예정된 다운로드가 많다면 그 모든 콜백을 받게 됩니다 이때 다운로드 객체의 고유한 식별자로 이런 걸 구별해야죠 BADownloadManager에 대리자가 생기는 순간 앱이 콜백을 받기 시작하죠 시스템이 콜백을 인큐하진 않습니다 앱이 대리자 메서드를 처리하지 않거나 대리자를 만들지 않았다면 익스텐션이 활성화돼 메시지를 처리합니다 이러면 충분히 예상해야 할 점이 앱의 BADownloadManager에 대리자가 없으면 익스텐션이 메시지를 받는다는 거죠 사용자에게 제시되는 포어그라운드에 앱이 있고 대리자가 만들어져 있다면 앱이 콜백을 받게 되고 익스텐션은 활성화 안 되죠 앱이 대리자 콜백을 처리하지 않을 때만 익스텐션이 활성화됩니다 다운로드가 끝나거나 실패했는데 이 메시지를 앱이 처리 안 하면 익스텐션이 활성화돼요 콜백이 다 익스텐션을 활성화하지 않는 걸 기억해 두세요 BADownloadManagerDelegate와 BADownloaderExtension 프로토콜의 공용 인터페이스를 공유하는 콜백만 그러죠 다운로드 성공이나 실패는 대리자와 프로토콜 공용 인터페이스를 보여 주는 실례죠 앱 확장 프로그램에 활성화시키는 자체 진입점이 있지만 익스텐션이 실행 중이면 BADownloadManager로 대리자를 만들 수 있어요 이러면 앱과 익스텐션이 중복 메시지를 대리자로 받습니다 대리자 메시지를 처리하러 익스텐션이 활성화되진 않죠 BADownloaderExtension 프로토콜에서 정의한 익스텐션 진입점에서만 활성화돼요 다운로드 매니저 대리자의 프로토콜을 살펴볼게요 첫 번째 기능은 다운로드가 시작될 때마다 메시지를 받는 겁니다 기기가 특정 다운로드를 예정하기로 선택했을 때 추적하는 데 유용하죠 다운로드가 중지되면 통보받기도 합니다 중지되는 사례는 이런 겁니다 익스텐션이 백그라운드 다운로드를 시작해 앱이 포어그라운드로 촉진할지 물어볼 때죠 이렇게 촉진하면 다운로드가 중지됐다 재개되기 전에 작은 창이 생깁니다 포어그라운드에서 다운로드되면 다운로드 매니저로 다운로드 진척 상황을 모니터할 수도 있죠 챌린지 요청에 응답하는 장치도 제공하니 연결 진위 인증이나 연결을 인가하는 크리덴셜을 제공하는 데 유용합니다 가장 중요한 기능은 실패하거나 완료된 다운로드를 다루는 거죠 다운로드가 실패하면 다시 예정하거나 원인을 밝혀야 합니다 다운로드가 성공하려면 운영 체계가 관리하는 곳에 시스템이 파일을 배치해야죠 기기 저장 용량이 부족하면 시스템이 그 파일을 삭제해 줍니다 시스템이 제공하는 곳에 파일을 놔두길 강력하게 권유합니다 불가피할 때만 파일을 옮기고 부디 복사하지 마세요 나중에 원본 파일을 삭제하지 않는 한요 기억해 두세요, 다운로드 매니저 대리자 프로토콜로 앱이나 익스텐션이 예정한 다운로드와 관련된 메시지를 받는 겁니다 익스텐션 진입점은 그렇지 않으니 다음 주제로 넘어갈게요 이제 백그라운드 에셋의 가장 흥미로운 부분인 익스텐션을 살펴보죠 사용자가 앱을 시작하기 전에 익스텐션으로 에셋 다운로드를 예정할 수 있어요 이러면 에셋을 제자리에 두고 준비해 최소한의 대기 시간으로 최고의 앱 경험을 제공할 수 있습니다 앞서 얘기했듯 새로운 앱 확장 프로그램을 소개하는데 기존 프로젝트의 Xcode 안에서 익스텐션을 만들 수 있죠 간단히 상기하자면 익스텐션은 앱이 설치되거나 갱신될 때 실행됩니다 탄력적으로 늘 가장 최근의 에셋에 앱의 변화가 반영되게 해 주죠 앱 사용 빈도에 따라 익스텐션이 주기적으로 실행되기도 해요 날마다 앱을 쓴다면 앱이 이 행동을 학습해 익스텐션이 더 자주 실행됩니다 하지만 앱을 시작한 적이 없다면 주기적으로 확인하는 빈도가 감소합니다 새 익스텐션은 수명 주기도 짧아서 에셋만 다운로드하게 빠듯한 샌드박스로 그 사용량을 제한합니다 익스텐션에선 빨리 결정하길 권장하며 백그라운드 에셋 프레임워크에 익스텐션을 한정하세요 익스텐션을 둘러보기 전에 익스텐션 시작에 앞서 설정할 게 몇 가지 있습니다 App Store에서 앱 배포를 허가할 때도 이런 변경 사항이 필요 조건이죠 앱의 정보 재산권 목록에서 몇 가지 추가적인 키를 정의해야 해요 익스텐션이 아니라 앱의 정보 설정 파일에만 놔둬야 하는 키예요 첫 번째 키는 BAInitialDownload Restrictions로 여러분의 익스텐션에 자리 잡을 규제를 명시하는 사전입니다 최대한 정확하게 하고자 앱 심사 팀이 이 규제를 검토하죠 이젠 이 사전 안에 있는 각각의 키를 파헤쳐 보겠습니다 첫 번째 규제는 다운로드 허용량이에요 앱을 처음 설치할 때 익스텐션에서 여러분이 요청하는 최대 다운로드 용량이 바이트로 표시됩니다 여러분이 다운로드를 요청한 파일을 다 합친 총량이지 개별적인 파일의 용량이 아닙니다 다음 항목은 도메인 AllowList로 줄로 표시되는 도메인 모음입니다 도메인 AllowList은 접두사 와일드카드를 지원하고 익스텐션이 다운로드 허가받은 호스트명 목록을 받아들이죠 중요한 주의 사항은 앱이 처음 설치된 후에만 DownloadAllowance와 AllowList 같은 BAInitial DownloadRestrictions의 키가 실행된다는 겁니다 앱이 시작되면 이런 규제가 더는 시행되지 않아요 마지막으로 필요한 키는 정보 설정 파일 루트에 있죠 이런 에셋의 추가 저장 공간에 여러분 앱이 요청할 최대 용량입니다 압축된 에셋을 내려받고 싶으실 테니 이 값은 최종적으로 발췌한 비압축 용량이 돼야죠 여기 나오는 수치가 앱 다운로드 전에 App Store에 제시돼요 하우스키핑을 살펴봤으니 *하우스키핑/프로그램을 적절히 실행하기 위해해야 하는 시스템 운용 여러분 익스텐션의 진입점을 보다 상세히 다뤄 볼게요 프로토콜에서 정의한 기능은 앱이 아니라 시스템이 호출할 겁니다 익스텐션에 말하는 걸 응용 프로그램이 책임지는 다른 앱 확장 프로그램과 달리 백그라운드 다운로드 익스텐션은 시스템이 중개합니다 시스템이 익스텐션 수명 주기를 관리하니 임시적인 서비스로 봐야 해요 프로토콜 내부의 기능을 호출할 때마다 그곳의 작업량을 최소화하는 게 중요합니다 익스텐션은 설치된 후 빨리 종료되니까요 압축을 해제하거나 시간이 걸리는 복잡한 작업을 할 만한 장소가 못 됩니다 익스텐션 작업의 큰 장점 중 하나는 앱에서 쓰는 백그라운드 에셋 API를 익스텐션에서도 다 쓸 수 있다는 점입니다 유일한 예외는 ForegroundDownload API일 때죠 앱에서 쓰듯 BADownloadManager를 사용할 수 있다는 뜻입니다 사실 앱과 익스텐션에서 에셋을 예정하고 관리할 때와 같은 코드를 써서 뭔가 만들 수 있는 기능을 찾을 가능성이 크죠 또한 익스텐션을 만들 때 둘 다 공통 앱 그룹에 두는 게 중요해요 같은 그룹 식별자를 쓰면 앱과 익스텐션에서 그 콘텐츠를 읽고 쓸 수 있습니다 이제 익스텐션이 따르게 할 다운로더 익스텐션 프로토콜을 살펴보죠 우선 다운로드 매니저 대리자 프로토콜과 비슷한 점이 눈에 띄겠죠 앞서 말했듯이 BADownload Manager를 써서 익스텐션 안에서 대리자를 구성할 수 있어요 하지만 익스텐션을 활성화할 유일한 진입점이죠 첫 번째 기능은 처음 응용 프로그램이 설치될 때마다 실행되죠 앱과 달리 익스텐션은 시작된 상황입니다 다운로드를 예정하기 안성맞춤인 기회죠 앱이 시작된 후 최고의 경험을 선사하는 데 필요한 부분입니다 앱이 처음 설치될 땐 다운로드 규제가 시행되는 걸 기억하는 게 중요하죠 여러분이 정보 설정 파일에 정의한 BADownloadRestrictions 키를 찾아보세요 최대 허용 다운로드 용량과 허가된 도메인이 뭔지 알게요 다음 기능은 App Store가 앱을 갱신할 때마다 실행되죠 사용자가 앱 스위처에서 앱을 계속 쓰는 한 새로 갱신된 익스텐션이 활성화돼서 예정 작업을 시작할 수 있죠 checkForUpdates 기능은 시스템이 익스텐션을 주기적으로 확인하게 지원하니 백그라운드 다운로드에 필요한 업데이트를 확인할 수 있어요 시스템이 앱 사용 빈도에 따라 이 기능을 실행합니다 챌린지 요청 인증에 응답하는 것도 지원합니다 그래서 다운로드 파일의 출처가 믿을 만한지 통제하고 확인하게요 마지막으로 대리자처럼 다운로드가 실패하거나 성공하면 알려 주죠 backgroundDownload DidFail 기능에서 에러가 반환되지 않는 걸 알 수 있죠 반환된 BADownload 객체의 내부 변수 상태와 에러가 검색됩니다 마지막 세 기능은 익스텐션 다운로드가 예정되지 않아도 실행되니 주의하는 게 중요합니다 앱이 다운로드를 예정했는데 백그라운드로 전환되면 익스텐션이 다운로드를 맡게 됩니다 앱과 익스텐션의 BADownloaderManager 사용법을 파악했으니 앱과 익스텐션이 동시에 실행되는 의미를 생각해 보기 시작해야죠 예를 들어 업데이트를 주기적으로 확인하게 익스텐션을 활성화할 때라고 시스템이 결정했다 치죠 물론 익스텐션이 확인하려면 네트워크에 접속해야 하니 BADownloaderManager로 카탈로그 다운로드를 예정해요 아니면 사용 가능 한 업데이트된 에셋 목록을 제공하는 다른 메타데이터나요 예를 들어 파일이 100KB 카탈로그라고 치죠 다운로드해야 할 기가바이트 용량 에셋 목록이 거기 담겼고요 예정된 다운로드가 끝나거나 실패했는지 익스텐션이 알아야 하니 다운로드 매니저에 대리자를 첨부하게 되죠 다운로드 매니저의 대리자는 익스텐션 진입점에 쓰여요 예정될 대용량 에셋이 뭔지 파악하게 작은 파일을 다운로드하니 익스텐션 진입점이 즉각 실행된다는 보장이 없습니다 다운로드가 끝나면 익스텐션이 대리자를 통해 이 메시지를 받죠 익스텐션은 카탈로그 파일에 접속해 다운로드 파일을 처리할 계획에 따라 결정해야죠 기기에 내려받아야 할 에셋이 뭔지 파악하게 익스텐션이 파일을 읽겠죠 그럼 익스텐션이 대용량 에셋의 백그라운드 다운로드를 예정할 수 있죠 이젠 다운로드한 파일이 필요 없으니 익스텐션이 파일을 삭제해야 해요 적절해 보이지만 익스텐션이 실행돼 BADownloadManager를 만들 때 앱이 시작되면 어떻게 될까요? 지금부터 살펴볼게요 앱은 시작되는 즉시 갱신된 콘텐츠가 있는지 파악하려고 합니다 버전 번호는 앱 그룹에 저장될 테니 둘 다 에셋이 업데이트됐나 파악하게 찾아보겠죠 최신 카탈로그 다운로드가 끝나기 전에 앱이 시작됐으니 매니저의 현재 다운로드를 불러와요 그리고 카탈로그 다운로드가 진행 중이니 대리자에서 끝날 때까지 기다립니다 하지만 문제가 있죠 익스텐션과 앱이 다운로드 매니저와 연결된 각각의 대리자로 다운로드 종료 메시지를 받거든요 파일 다운로드 때 데이터 레이스를 한다는 뜻이죠 앱과 익스텐션이 동시에 파일을 읽고 삭제하려 드니 곤란하죠 이러면 앱이나 익스텐션이 파일을 읽으려다 사라질 수도 있어요 앱에 있는 두 가닥 실과 비슷한 상황이란 의미로 보고 앱과 익스텐션에 대해 생각해 봐야죠 다행히 백그라운드 에셋이 앱과 익스텐션을 동조화시킬 방법을 제공하니 그걸 얘기해 볼게요 앱과 익스텐션 동조는 백그라운드 에셋에서 굉장히 간단한 일이죠 지금 보시는 건 다운로드 완료시 다운로드 매니저 대리자의 기능입니다 앱이나 익스텐션이 접속하는 파일의 로컬 경로가 담긴 URL이 나옵니다 이 예시에선 이 파일이 상호 배제됐나 확인할 겁니다 그리고 다운로드 매니저에 참조하고 withExclusiveControl 기능을 써서 완료 핸들러를 인수합니다 완료 핸들러 영역에서 실행되는 코드는 다 배타 제어에 필요한 다른 호출과 상호 배제하게끔 보장됩니다 앱이 완료 핸들러에서 돌아오기 전에 익스텐션이 withExclusive Control을 호출하면 기다려야 한다는 의미인데 그 반대로도 적용됩니다 익스텐션이 배타 제어권을 먼저 얻으면 익스텐션이 끝나거나 종료 스코프로 제어권을 내놓을 때까지 앱이 기다리죠 배타 제어 획득이 실패할 수 있다는 걸 기억하는 게 중요하죠 이렇게 될 가능성은 극히 희박하지만 이럴 경우엔 코드가 처리해야 합니다 기능상의 에러가 발생했나 확인하면 배타 제어를 얻을 수 없는지 감지할 수 있어요 이때부턴 앱이나 익스텐션이 컨텍스트에서 배타 접근권을 가진다고 보장할 수 있죠 앞선 예시를 바탕으로 파일 콘텐츠를 읽고 정리하기를 선택할 수 있다는 게 완전히 타당해졌죠 이것만 알아 두세요 이미 처리한 파일인 걸 알고 다른 앱이나 익스텐션이 배타 제어에 착수할 기회를 얻는다면 우선 파일이 존재하거나 데이터베이스나 설정 파일에 쓰는지 확인해 완수할 수도 있죠 기억해 두세요, 백그라운드 다운로더 익스텐션은 앱의 대용량 에셋 다운로드를 모으고 예정하는 용도예요 런타임이 짧으니까 익스텐션 내 작업량은 부디 최소화해 주세요 그리고 공유 앱 그룹에 앱과 익스텐션을 배치해야 서로 다운로드한 파일에 접속할 수 있습니다 마지막으로 앱이 아니라 시스템이 익스텐션을 중개합니다 기본적인 백그라운드 다운로드 익스텐션 개발법을 아셨으니 앱에서 백그라운드 에셋을 실행할 준비가 다 됐어요 그동안 배운 걸 복습하죠 다운로드 매니저는 앱과 익스텐션의 다운로드를 조정하고 예정하는 데 씁니다 그러니 다운로드 매니저를 양쪽에서 써야죠 앱이 포어그라운드에 없어도 익스텐션은 실행돼요 이런 경우는 앱 설치와 업데이트나 시스템이 결정하는 주기적인 간격에 생기죠 앱이 시작돼서 백그라운드에서 내려받은 콘텐츠가 대기할 때는 즉시 포어그라운드로 다운로드하게 촉진하세요 익스텐션은 백그라운드 다운로드만 예정할 수 있죠 앱이 포어그라운드 다운로드를 촉진하면 콘텐츠를 최대한 빨리 내려받을 수 있어요 다운로드 매니저에 배타적 접근이 필요하면 부디 배타 제어 API를 사용해 주세요 이러면 앱이나 익스텐션만이 그때 런타임을 가질 수 있죠 컨테이너에 접속하거나 다운로드 관리할 때 익스텐션이 앱과 경쟁한다고 생각할 필요가 없으니 굉장히 유용합니다 이 교육에서 꼭 얻을 지식이 있다면 기다리는 게 안 좋은 앱 경험이란 거죠 여러분이 기다리는 작업이 진행될 때 앱을 써서 대기 시간을 최소화하세요 앱 대기 시간을 최소화하는 방법 중 하나가 백그라운드 다운로드 익스텐션이 포함된 새 백그라운드 에셋 프레임워크를 쓰는 거죠 이러면 앱이 시작되기 전에 앱이 콘텐츠를 다 준비하는 데 유용합니다 설명서도 꼭 확인하세요 이 교육에 포함되지 않았을 수 있는 추가적인 정보가 담겼으니까요 익스텐션을 테스트하고 진입점을 시뮬레이션하는 방법 같은 거죠 백그라운드 에셋을 소개해서 참 기쁘고 여러분의 평가를 중시하니까 Feedback Assistant를 써서 알려 주세요 유용한 점과 개선해 주길 바라는 부분을요 새 프레임워크라서 배포 기간에 수정할 수 있는 기회가 있습니다 여러분께 흥미로울 추가적인 세션이 있으니 살펴보시길 권장합니다 'HTTP3로 네트워킹 가속화'는 훌륭한 세션이고 백그라운드 에셋과 잘 맞아요 또 살펴보시라고 추천할 세션이 있어요 '주문형 리소스 소개'란 교육인데 애플이 호스팅하는 콘텐츠고 요청해서 내려받는 파일일 때 백그라운드 에셋의 대안을 다 다뤄요 둘 다 흥미진진하고 배울 게 많은 세션이죠 함께해 주셔서 감사합니다 애플 전 직원을 대신해 WWDC를 즐기시길 빕니다 ♪
-
-
5:28 - Getting started with Background Assets
// Getting started with Background Assets import BackgroundAssets let url = URL(string: "https://cdn.example.com/large-asset.bin")! let appGroupIdentifier = "group.WWDC.AssetContainer" let download = BAURLDownload ( identifier: "Large-Asset", request: URLRequest(url:url), applicationGroupIdentifier: appGroupIdentifier ) let manager = BADownloadManager.shared manager.delegate = self // BADownloadManagerDelegate protocol // Schedule download at an opportunistic time determined by the system do { try manager.schedule(download) } catch { print("Failed to schedule download. \(error)") } // or Schedule download in foreground do { try manager.startForegroundDownload(download) } catch { print("Failed to start foreground download. \(error)") } // or Promote downloads to foreground. do { for download in try await manager.fetchCurrentDownloads) { try manager.startForegroundDownload(download) } } catch { print("Failed to promote downloads to foreground \(error)") }
-
10:28 - BADownloadManager delegate protocol
// BADownloadManager protocol definition public protocol BADownloadManagerDelegate : NSObjectProtocol { optional func downloadDidBegin(_ download: BADownload) optional func downloadDidPause(_ download: BADownload) optional func download(_ download: BADownload, bytesWritten: Int64, totalBytesWritten: Int64, totalExpectedBytes: Int64) optional func download(_ download: BADownload, didReceive challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) optional func download(_ download: BADownload, failedWithError error: Error) optional func download(_ download: BADownload, finishedWithFileURL fileURL: URL) }
-
15:37 - BADownloaderExtension protocol
// BADownloaderExtension protocol definition public protocol BADownloaderExtension : NSObjectProtocol { optional func applicationDidInstall(metadata: BAApplicationExtensionInfo) optional func applicationDidUpdate(metadata: BAApplicationExtensionInfo) optional func checkForUpdates(metadata: BAApplicationExtensionInfo) optional func download(_ download: BADownload, didReceive challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) optional func backgroundDownloadDidFail(failedDownload: BADownload) optional func backgroundDownloadDidFinish(finishedDownload: BADownload, fileURL: URL) optional func extensionWillTerminate() }
-
19:40 - Synchronizing between app and extension
// Synchronizing between app and extension func download(_ download: BADownload, finishedWithFileURL fileURL: URL) { let manager = BADownloadManager.shared manager.withExclusiveControl { error in guard error == nil else { print("Unable to acquire exclusive control \(String(describing: error))") return } // Exclusive control acquired // All code in this scope ensures mutual exclusion between extension and app do { let data = try Data(contentsOf: fileURL, options: .mappedIfSafe) // Do something with memory mapped data try FileManager.default.removeItem(at: fileURL) } catch { print("Unable to read/cleanup file data. \(error)") } } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.