"웹 껍데기는 다리를 건너서 플랫폼에 닿아. 네이티브 앱은 처음부터 그 위에 서 있고."
시작은 웹이었어
CWK 앱 가족이 처음부터 Swift였던 건 아니야. 첫 데스크톱 도구들은 웹 화면을 얇은 네이티브 껍데기로 감싼 거였고, 폰 쪽은 사설망 너머로 여는 PWA였어. 그땐 그게 맞았어. 코드베이스는 하나고, 고치고 확인하는 속도가 빠르고, 글자랑 표 그리는 건 브라우저 엔진이 이미 잘하니까.
그러다 앱들이 욕심이 생겼어. 받아쓰기 유틸리티는 다른 앱에 포커스가 있어도 글자를 넣어야 하니까 전역 단축키랑 손쉬운 사용 API가 필요했어. 글쓰기 편집기는 한글 조합이 다른 맥 앱이랑 똑같이 동작하는 진짜 텍스트 시스템이 필요했고. 폰 캡처 앱은 공유 시트, 푸시, 위젯, 워치 페이스 버튼까지 원했지. 이걸 웹 껍데기로 못 하는 건 아니야. 플러그인, 브릿지, 권한 우회로 닿긴 해. 문제는 다리 하나 놓을 때마다 조용히 망가질 구멍이 하나씩 늘어난다는 거였어. 그래서 앱들이 하나씩 Swift로 넘어왔어. 글쓰기 편집기는 네이티브 AppKit 앱이 됐고, 터미널이랑 파일 작업대는 처음부터 네이티브로 태어났어. 지금은 앱 여덟 개가 TestFlight를 거쳐 아이폰과 아이패드에 올라가.
네이티브로 실제로 얻는 것
- 텍스트 시스템. Mac의
NSTextView, iOS의UITextView엔 입력기, 맞춤법 검사, 받아쓰기, 손쉬운 사용이 수십 년치 쌓여 있어. 한글 조합 중인 글자 처리를 네가 다시 짜고 싶진 않을 거야. - 시스템 시민권. 메뉴 막대 아이템, 전역 단축키, LaunchAgent, URL 스킴, 손쉬운 사용 API, 키체인. 전부 정식으로 쓸 수 있고, 전부 앱 서명에 묶인 권한 모델(TCC) 하나로 관리돼.
- 웹 페이지가 절대 못 가지는 화면. 공유 확장, App Intents랑 액션 버튼, 위젯이랑 Live Activity, 백그라운드 오디오, 믿을 만한 푸시, 그리고 워치.
- 애플 기기 전부에서 한 언어. Swift 패키지 하나에 모델이랑 전송 형식을 넣어두면 맥 앱, 아이폰 앱, 워치 앱이 같이 써.
대신 치르는 것
네이티브가 공짜는 아니야. 애플 툴체인과 1년 단위로 돌아가는 릴리스 주기를 받아들여야 해. UI도 플랫폼 관용구에 맞춰 따로 짜야 해(AppKit이랑 UIKit은 아직 현역이야). 코드 서명은 포장하는 단계가 아니라 앱의 정체성 그 자체야. iPhone, iPad, 워치 앱은 배달도 애플 서버를 거쳐야 해. 이 퀘스트가 있는 이유가 딱 이거야. 전부 배울 수 있는 거고, 대부분은 가족 앱들이 한 번씩 물린 다음에야 글로 남았거든.
하필 Swift인 이유
AppKit이랑 UIKit 밑엔 아직 Objective-C가 많이 깔려 있어서, 델리게이트 프로토콜이나 블록 타입에서 계속 마주칠 거야. 그래도 새 애플 API는 Swift를 먼저 염두에 두고 설계되고, SwiftUI랑 Observation은 Swift에만 있어. 그리고 Swift 6는 데이터 경합을 컴파일할 때 잡아내는데, 바로 그런 버그가 실제 폰에서 가족 앱을 죽인 적이 있거든. 그래서 이 퀘스트는 Swift로 쓰고, Objective-C는 플랫폼이 억지로 들이밀 때만 읽어.