Command Palette

Search for a command to run...

LazyPad 3편에서는 손을 뗐다가 다시 올리는 첫 입력 문제를 build 0.1.0 (10) physical smoke 기준선까지 좁힌 과정을 정리했습니다.

입력감 기준선이 생기면 다음 문제는 코드가 아니었습니다. 외부 사용자가 실제로 설치하고 테스트할 수 있는 경로를 만들어야 했습니다.

LazyPad는 iPhone 앱 하나로 끝나는 제품이 아닙니다. Mac Companion이 필요하고, Mac Companion은 Accessibility permission이 필요합니다. iOS 쪽은 TestFlight 심사와 tester invite 흐름을 지나야 합니다. 지원 주소와 privacy/support page도 필요합니다.

이번 글은 이 코드 밖의 gate를 정리합니다. 핵심은 "배포 완료"가 아니라 "배포 후보를 검증할 수 있는 상태"를 정확하게 말하는 것입니다.

배포 용어를 알아야 코드 밖 gate가 보입니다

이번 글은 코드보다 배포 절차가 많습니다. 그래서 Apple 생태계와 macOS 보안 절차에서 쓰는 단어를 먼저 정리합니다.

용어쉬운 설명LazyPad에서의 의미
TestFlightApp Store 정식 출시 전 iOS 앱을 테스터에게 전달하는 Apple 테스트 배포 경로입니다외부 사용자가 iPhone 앱을 설치할 수 있는 공식 beta 경로입니다
App Store ConnectiOS 앱 등록, build 업로드, TestFlight 심사 정보를 관리하는 Apple 웹 서비스입니다build 0.1.0 (11)을 외부 TestFlight 심사에 올린 장소입니다
Apple Beta App Review외부 TestFlight 배포 전에 Apple이 beta 앱을 검토하는 절차입니다외부 초대 전에 남아 있는 gate입니다
Tester invite심사 뒤 외부 tester에게 설치 초대를 보내는 단계입니다아직 완료됐다고 말하지 않는 단계입니다
Mac CompanionMac에서 실제 입력을 실행하는 별도 앱입니다iPhone 앱과 함께 있어야 LazyPad가 동작합니다
.app bundlemacOS 앱을 하나의 앱처럼 보이게 묶은 폴더 구조입니다외부 사용자가 설치하고 실행하는 Mac 배포물 형태입니다
Developer IDApp Store 밖에서 배포하는 Mac 앱에 개발자 신원을 붙이는 Apple 서명 체계입니다Mac Companion을 외부 배포물로 설명하려면 필요했습니다
NotarizationApple이 Mac 앱을 검사하고 배포 가능 상태로 확인해주는 절차입니다사용자가 앱을 열 때 macOS 보안 경고를 줄이기 위해 필요했습니다
Staplingnotarization ticket을 앱에 붙여두는 절차입니다사용자의 Mac이 오프라인이거나 확인이 늦어도 앱 상태를 증명하기 쉽게 합니다
GatekeepermacOS가 앱 실행 전에 안전성을 확인하는 보안 기능입니다외부 zip을 풀어도 앱이 열릴 수 있는지 확인하는 gate였습니다
Artifact검증 대상이 되는 실제 배포 파일입니다코드가 아니라 사용자가 받는 .app 또는 .zip을 뜻합니다

iOS 앱 하나로는 외부 테스트가 시작되지 않았습니다

LazyPad는 paired Mac에 입력을 보내는 앱입니다. 그래서 iPhone 앱만 준비되면 끝나는 구조가 아니었습니다.

외부 사용자가 테스트하려면 다음 네 가지가 함께 필요했습니다.

구성필요한 이유
iOS TestFlight buildiPhone 앱을 외부 tester에게 전달하는 경로입니다
Mac Companion .appMac에서 pointer, click, scroll, drag event를 실행하는 실행면입니다
Accessibility permission 안내macOS 입력 실행에 필요한 권한을 사용자가 이해해야 합니다
support/privacy 표면설치 전후 질문과 local-first 경계를 설명해야 합니다

이 네 가지 중 하나라도 비어 있으면 "외부 사용자가 테스트할 수 있다"고 말하기 어렵습니다. 그래서 기능 구현 이후에는 release gate를 별도 작업으로 분리했습니다.

build 10과 build 11의 역할을 분리했습니다

LazyPad 문서에는 build 0.1.0 (10)과 build 0.1.0 (11)이 함께 등장합니다.

두 build는 같은 의미가 아닙니다. 이 구분을 먼저 두어야 현재 상태를 과장하지 않을 수 있습니다.

build역할말할 수 있는 범위
0.1.0 (10)입력감과 Mac Companion 배포물 검증 기준선lift/re-touch, fast movement feel, drag regression, Mac signing/notarization/zip 검증 기준으로 설명할 수 있습니다
0.1.0 (11)App Store Connect 외부 TestFlight 심사 제출 build외부 그룹에 올리고 Apple Beta App Review에 제출한 상태로 설명할 수 있습니다

build 10은 제품 동작과 Mac artifact를 설명하는 기준선입니다. build 11은 외부 TestFlight 흐름에 올린 build입니다.

따라서 "외부 테스트 완료"라고 쓰지 않습니다. 현재 안전한 표현은 외부 TestFlight 심사 제출과 심사 대기입니다.

Mac Companion은 별도의 배포물로 검증했습니다

Mac Companion은 iPhone 앱의 보조 파일이 아닙니다. Mac에서 실제 입력을 실행하는 별도 앱입니다.

그래서 외부 사용자가 설치할 수 있는 배포물로 만들려면 macOS 보안 gate를 통과해야 했습니다.

초보자 기준으로 보면 흐름은 다음과 같습니다.

  1. Mac 실행 파일을 release build로 만듭니다.
  2. LazyPad Companion.app bundle로 감쌉니다.
  3. Developer ID로 app을 signing합니다.
  4. signed app을 zip으로 묶어 Apple notarization에 제출합니다.
  5. Apple이 accepted를 반환하면 ticket을 app에 stapling합니다.
  6. stapled app을 codesign, stapler validate, Gatekeeper로 다시 확인합니다.
  7. 최종 zip을 다시 만들고, unzip한 app도 같은 검증을 통과하는지 확인합니다.

이 과정이 필요한 이유는 단순합니다. 배포 직전에 통과한 app이, zip으로 전달된 뒤에도 같은 상태로 열려야 하기 때문입니다.

각 단계를 조금 더 풀면 다음과 같습니다.

단계설명
Release build개발 중 확인용 build가 아니라 외부 전달을 전제로 만든 build입니다
App bundle실행 파일, 아이콘, 권한 정보 등을 macOS 앱 형태로 묶은 구조입니다
Signing"이 앱은 이 개발자가 만들었습니다"라는 암호화된 서명을 붙이는 절차입니다
NotarizationApple에 제출해 악성 코드 검사와 배포 가능 확인을 받는 절차입니다
Staplingnotarization 결과 ticket을 앱에 붙이는 절차입니다
codesign verification앱 서명이 깨지지 않았는지 명령으로 확인하는 절차입니다
stapler validatenotarization ticket이 앱에 제대로 붙었는지 확인하는 절차입니다
Gatekeeper assessmentmacOS가 이 앱을 실행 가능한 배포물로 받아들이는지 확인하는 절차입니다
Zip/unzip verification압축해서 전달한 뒤 다시 풀어도 서명과 ticket이 유지되는지 확인하는 절차입니다

build 10 계열 Mac Companion은 다음 검증을 통과했습니다.

gate상태
release build통과
Developer ID signing통과
Apple notarizationaccepted
ticket stapling통과
strict codesign verification통과
stapler validation통과
Gatekeeper assessmentNotarized Developer ID로 accepted
final zip recreation통과
unzip verificationstrict codesign, stapler validation, Gatekeeper assessment 통과

이 결과로 Mac Companion artifact gate는 닫혔습니다. 다만 iOS 외부 TestFlight 심사와 tester invitation은 별도 gate로 남아 있었습니다.

TestFlight는 upload가 아니라 심사 흐름이었습니다

처음에는 TestFlight를 build upload 중심으로 생각하기 쉽습니다. 실제 외부 테스트에서는 그보다 많은 표면이 필요했습니다.

App Store Connect에는 test information이 필요했습니다. Beta App Description, Feedback Email, Review Contact, Review Notes, What to Test를 채워야 했습니다.

이 항목들은 단순 양식이 아니었습니다. Apple reviewer와 외부 tester가 앱의 목적, 테스트 범위, 연락 경로를 이해하기 위한 설명이었습니다.

항목쉬운 설명
Beta App Descriptionbeta 앱이 무엇을 하는지 설명하는 문장입니다
Feedback Emailtester가 문제를 보낼 수 있는 공개 연락 주소입니다
Review ContactApple review 과정에서 연락할 수 있는 정보입니다
Review Notesreviewer가 앱을 어떻게 확인해야 하는지 적는 안내입니다
What to Test이번 beta에서 tester가 무엇을 확인하면 되는지 적는 문장입니다
External group외부 tester를 묶는 TestFlight 그룹입니다

여기서 중요한 판단은 공개 지원 주소였습니다. 개인 이메일 대신 support@lazypad.app을 만들고, 테스트 메일 송수신까지 확인했습니다. 이 주소를 feedback/review contact용 공개 지원 경로로 사용했습니다.

외부 TestFlight 흐름은 다음 순서로 정리했습니다.

단계상태
build number bumpbuild 0.1.0 (11)로 올렸습니다
Xcode Organizer upload업로드 완료 화면을 확인했습니다
support emailsupport@lazypad.app 송수신을 확인했습니다
test informationBeta App Description, Feedback Email, Review Notes, What to Test를 정리했습니다
external groupExternal Beta 0.1 그룹을 만들었습니다
review submissionbuild 0.1.0 (11)을 Apple Beta App Review에 제출했습니다
tester inviteApple Beta App Review 이후로 남아 있습니다

이 상태는 배포 완료가 아닙니다. 외부 사용자가 설치하기 전 단계입니다. 그래서 글에서도 "심사 제출"과 "초대 완료"를 분리해서 말합니다.

support와 privacy page도 제품의 일부였습니다

외부 사용자는 code diff를 보지 않습니다. 사용자는 설치 전에 무엇을 믿어야 하는지 봅니다.

LazyPad에서는 이 설명이 특히 중요했습니다. Mac Companion은 Accessibility permission을 요구하고, iPhone과 Mac은 같은 local network에서 연결됩니다. 이 설명이 부족하면 기능이 맞아도 설치 단계에서 신뢰를 잃을 수 있습니다.

그래서 lazypad.app 정적 초안을 만들었습니다.

페이지역할
/LazyPad가 무엇을 하는지와 현재 beta candidate 상태를 설명합니다
/support/Mac Companion 설치, Accessibility permission, pairing/test flow를 설명합니다
/privacy/local-first, no cloud relay, raw evidence boundary를 설명합니다

Local-first는 입력이 기본적으로 가까운 iPhone과 Mac 사이에서 처리된다는 뜻입니다. No cloud relay는 runtime input control을 cloud server를 거쳐 보내지 않는다는 뜻입니다.

Raw evidence boundary는 개발 중 확인한 원본 로그, 계정 값, device identifier 같은 민감 정보를 공개 글이나 저장소에 그대로 남기지 않는 원칙입니다. LazyPad는 입력 앱이기 때문에 기능 설명만큼 이 경계도 중요했습니다.

문구는 보수적으로 잡았습니다. External TestFlight pending, Mac Companion artifact verified, private beta candidate처럼 현재 상태를 넘지 않는 표현만 사용했습니다.

말하지 않는 표현을 먼저 정했습니다

배포 직전 단계에서는 무엇을 했는지보다 무엇을 아직 말하지 않는지가 중요했습니다.

사용하지 않는 표현이유
정식 출시App Store release 상태가 아닙니다
외부 테스트 완료Apple Beta App Review와 tester invitation이 남아 있습니다
public beta opened첫 external group invite가 완료되지 않았습니다
Magic Trackpad replacementv0.1 scope가 아닙니다
Bluetooth trackpad현재 구조가 Wi-Fi/Bonjour + Mac Companion입니다
remote desktop화면 제어나 원격 데스크톱 제품이 아닙니다

이 경계는 글쓰기만의 문제가 아니었습니다. 제품 문장, TestFlight review note, support page, privacy page가 모두 같은 경계를 지켜야 했습니다.

AI는 checklist를 만들었고, gate는 직접 통과시켰습니다

AI는 release gate를 정리하는 데 도움이 됐습니다.

Mac Companion packaging 순서를 설명하고, TestFlight packet 초안을 만들고, forbidden claim을 찾아내고, support/privacy 문구를 보수적으로 다듬는 데 사용할 수 있었습니다.

하지만 실제 gate는 직접 통과해야 했습니다.

AI로 빠르게 한 일직접 확인한 일
Mac packaging checklist 정리signing, notarization, stapling, Gatekeeper, zip/unzip verification 결과
TestFlight review note 초안App Store Connect에 필요한 정보 입력과 제출 상태
support/privacy 문구 정리support@lazypad.app 송수신 확인
claim boundary 점검완료, 대기, 금지 표현 분리

이 과정에서 AI 활용 능력은 속도만의 문제가 아니었습니다. AI가 만든 checklist가 실제 gate와 맞는지 확인하는 능력이 더 중요했습니다.

이번 시즌의 결론은 배포 완료가 아니라 후보 검증입니다

LazyPad 1차 개발기 시즌은 여기서 닫을 수 있습니다.

1편에서는 처음 다루는 Swift/Xcode와 AI-assisted learning loop로 iPhone-Mac 앱을 만든 전체 흐름을 정리했습니다. 2편에서는 입력감 알고리즘과 핵심 용어를 풀었습니다. 3편에서는 cursor reacquire 문제를 build 10 입력감 기준선으로 좁힌 과정을 정리했습니다. 4편에서는 외부 사용자가 설치할 수 있는 후보가 되기 위해 필요한 TestFlight, Mac Companion, support/privacy gate를 정리했습니다.

현재 결론은 명확합니다.

영역현재 상태
입력감 기준선build 0.1.0 (10) physical smoke 기준으로 설명 가능
Mac Companionsigned/notarized/stapled/Gatekeeper/zip-unzip verified artifact로 설명 가능
iOS TestFlightbuild 0.1.0 (11) external group + Apple Beta App Review 제출 상태
support emailsupport@lazypad.app 송수신 확인
웹 표면lazypad.app landing/support/privacy 초안 준비
외부 tester 운영Apple review와 invitation 이후 별도 기록 필요

다음 글은 실제 외부 tester가 설치한 뒤에 쓰겠습니다. 승인, 반려, 첫 feedback, 설치 실패, permission confusion 같은 운영 증거가 생기면 그때 다시 돌아오겠습니다.

이어 읽기

시리즈는 순서대로, 편집 추천은 맥락대로, 비슷한 주제는 태그 기준으로 정리합니다.

시리즈 전체

LazyPad 개발기: 아이폰을 맥 입력면으로 만들기4/4
  1. 1.LazyPad 개발기 1: 처음 쓰는 Swift와 Xcode로 iPhone-Mac 앱 배포 후보 만들기
  2. 2.LazyPad 개발기 2: 터치 입력감은 왜 배율 하나로 해결되지 않았나
  3. 3.LazyPad 개발기 3: 첫 재터치에서 드러난 커서 입력감 디버깅
  4. 4.LazyPad 개발기 4: TestFlight와 Mac Companion 배포 후보 검증

함께 읽으면 좋은 글

편집 추천

비슷한 주제의 글

태그가 겹치는 글입니다. 시리즈와 편집 추천에 이미 나온 글은 제외합니다.