"애플이 예뻐서가 아니라 1년에 그 정도 투자는 할만해."
모든 단계를 지나는 길 하나
이 퀘스트는 Spark라는 작은 앱 가족 하나를 패키지부터 폰까지 따라왔어. 이 레슨에선 그 길 전체를 한곳에 모아. 조각들이 실제로 생겨나야 하는 순서대로 늘어놓고, 단계마다 근거가 되는 레슨을 함께 짚어. 핵심은 순서야. 앞 트랙들에서 본 함정 여러 개가, 진짜 순서가 아니라 직관적인 순서대로 밟은 단계에서 나왔거든.
공유 로직부터
Swift 6 언어 모드의 Swift 패키지로 시작해. 데이터 경쟁은 누군가의 폰에서 트랩으로 터지기 전에, 네 책상 앞에서 컴파일 에러로 잡혀야 하니까. 두 앱이 같이 쓰는 값, Codable 타입, 규칙은 라이브러리 타깃에 둬. 저장하는 문서 타입마다 명시적인 init(from:)을 둬서, 처음으로 필드가 늘어날 때 기존 파일을 날리지 않고 옮겨갈 수 있게 해. 순수 로직은 그 코드가 있는 곳에서 바로 Swift Testing으로 테스트해. 그리고 메인 액터 맥락에서 Objective-C API에 넘기는 클로저는 사소하게 넘길 게 아니라 꼭 리뷰할 항목이라는 걸 기억해.
Mac 앱
먼저 앱의 구조를 골라. 입력 조합과 분할 뷰가 중요하다면 창과 텍스트는 AppKit이 맡고, 설정과 폼은 SwiftUI가 맡고, @Observable 모델이 양쪽에 데이터를 대. 빌드는 SwiftPM과 스크립트로 해. 스크립트가 번들을 조립하고, 확장 속성을 지우고, 자체 서명 신원 하나로 서명하고, 이름 바꾸기로 설치한 뒤, 최종 경로에서 검증해. designated requirement가 해시가 아니라 인증서를 가리키는지 확인해서 다음 빌드에도 권한이 살아남게 해. 유틸리티라면 실패했을 때만 다시 켜주는 LaunchAgent를 붙여. 설치된 번들은 해시 검사와 마감을 건 단계로 증명하고, 그 빌드 하나의 사본을 다른 Mac들에 보내.
폰 앱
project.yml로 Xcode 프로젝트를 생성해. 구성은 유니버설 타깃 하나, 소스에 적은 팀, 공유 확장과 App Group, 그리고 손목에서 담는 게 어울리는 앱이라면 워치 앱까지야. 클라이언트는 얇게 유지해. 필요한 건 깐깐한 엔진 주소, HTTPS 쌍둥이 주소나 단독 ATS 키, 모든 호출에 거는 바이트 예산, 명령을 다시 보내지 않고 재연결하는 소켓, 로컬에 쓰는 순간 담기가 끝나는 아웃박스야. 테스트는 전용 시뮬레이터에서 돌리고 모든 건너뛰기를 시끄럽게 만들어. 그러고 나서 시뮬레이터가 못 돌려보는 게 뭔지 기억해. 마이크, Data Protection, 메일에서 온 진짜 공유야.
배포
아카이브부터 해서 식별자가 생기게 하고, 그 뒤에 번들 id를 골라서 App Store Connect 레코드를 만들어. 팀 API 키로 인증해. 파이프라인이 더러운 입력을 거부하고, 소스에서 빌드 번호를 올리고, 로그를 남기며 아카이브하게 해. 이어서 아카이브를 관문에서 검사하고, 종료 상태와 실패 표시를 확인한 뒤에 올리게 해. 이 파이프라인이 찍어주는 건 네 사실 중 첫 번째야. 처리됨, 배정됨, 설치됨은 각각 별개의 사실이고, 설치됨은 기기에서 읽은 숫자로 확인해.
이 중 어느 것도 무료 계정으론 안 돼. 이 퀘스트가 처음부터 전제로 깔았던 조건이 바로 그거야. 멤버십 비용 안에 TestFlight, App Store Connect 레코드, 확장끼리 나눠 쓰는 App Group, 푸시 키가 다 들어 있어. 뒤쪽 트랙은 전부 그 위에 서 있어. 나머지는 이 마지막 트랙의 이름이 된 규율이야. 위에서 따라온 길의 모든 주장은 규칙이 되기 전에 누군가 직접 재본 거야. 네가 보탤 다음 주장도 그래야 해.