첫 조치는 같은 파일을 다시 제출하는 것이 아니라 notarytool 상태와 로그를 확인하는 것입니다. 인증, 서명, 포장, 티켓 가운데 실패 지점을 찾은 뒤 최종 배포 파일을 고치고, Accepted 이후에는 staple과 Gatekeeper 검증까지 끝내야 합니다. 이 순서를 지키면 macOS 앱 공증 실패를 재제출 반복으로 키우지 않을 수 있습니다.
이 글은 Developer ID로 Mac App Store 밖에서 앱을 배포하는 독립 개발자를 위한 내용입니다. 원격 Mac이나 CI에서 notarytool과 stapler를 관리하는 사람, 플러그인·보조 도구·DMG·PKG가 포함된 작은 팀에도 맞습니다.
시간표부터 잡기: 실패한 파일을 보존하고 단계부터 나누기
짧은 사례를 보겠습니다. 한 개발자는 DMG를 다시 만들지 않고 제출만 반복했습니다. 어느 시점에는 Invalid가 나왔고, 다른 제출물에는 Accepted가 표시됐지만 사용자의 Mac에서 실행이 막혔습니다. 두 결과는 같은 문제를 뜻하지 않습니다.
먼저 다음 항목을 별도 폴더에 복사하십시오.
- 제출 ID와
notarytool명령 출력 - 제출한 ZIP, DMG 또는 PKG의 최종 해시
- 사용한 Xcode 경로와
xcrun경로 - 서명에 사용한 인증서 이름과 팀 식별자
- 공증 로그와 최종 Gatekeeper 결과
- 배포에 사용한 Bundle ID와 파일 경로
실제 값은 로그와 저장소에서 확인하되, 문서나 이슈를 공유할 때는 Apple ID, 팀 식별자, 인증서 이름, 제출 ID, Bundle ID, 호스트 주소와 자격 증명을 모두 가리십시오.
공증 흐름은 Build → Archive → Export → Sign → Package → Submit → Accepted → Staple → Gatekeeper 검사로 나누어 기록하는 편이 좋습니다. Build가 성공했다는 사실은 Submit이나 사용자 측 실행까지 보장하지 않습니다.
altool을 새 자동화에 넣는 것도 피해야 합니다. Apple 기술 문서는 공증 서비스가 2023년 11월 1일부터 altool 제출을 받지 않는다고 설명하며, 최신 명령줄 흐름으로 notarytool을 안내합니다. 최신 공증 도구로 옮기는 공식 기술 문서를 기준으로 기존 스크립트를 다시 확인하십시오.
첫 번째 검사: 프로젝트가 아니라 최종 산출물을 비교하기
macOS 앱 공증 실패를 고칠 때 가장 흔한 실수는 Xcode 프로젝트 안의 원본 앱만 검사하는 것입니다. 실제 제출 파일이 ZIP인지 DMG인지 PKG인지 먼저 확인하고, 그 안에서 실행되는 모든 코드의 상태를 점검해야 합니다.
| 확인 대상 | 먼저 볼 증거 | 다음 조치 |
|---|---|---|
| 앱 본체 | Developer ID 서명, Hardened Runtime, 안전한 타임스탬프 | 서명 대상과 인증서 유형을 다시 확인합니다 |
| 프레임워크와 플러그인 | 중첩 코드의 서명과 권한 | 가장 안쪽 실행 파일부터 수정합니다 |
| 보조 도구와 로그인 항목 | 실제 설치 위치와 실행 파일 여부 | 누락된 구성 요소를 찾아 다시 포장합니다 |
| ZIP·DMG·PKG | 최종 포장 파일과 내부 경로 | 파일을 바꾼 뒤 외부 서명을 다시 수행합니다 |
| 배포 후 검사 | stapler validate, Gatekeeper 평가 |
개발 환경이 없는 Mac에서 설치합니다 |
codesign 출력에서 서명이 보인다고 끝나지 않습니다. Hardened Runtime이 활성화됐는지, 안전한 타임스탬프가 있는지, 권한 파일이 올바른 형식인지, get-task-allow가 배포용 결과에 남아 있지 않은지 확인하십시오.
앱 안의 Framework, 플러그인, 로그인 항목과 보조 실행 파일도 각각 문제를 일으킬 수 있습니다. Apple의 공증 전 배포 준비 문서는 배포 파일 자체를 기준으로 서명과 공증을 확인하는 흐름을 설명합니다.
서명한 뒤 Bundle의 파일을 교체하면 앞서 수행한 검사 결과를 신뢰할 수 없습니다. 아이콘, 설정 파일, 내장 실행 파일 또는 플러그인을 바꿨다면 해당 단계부터 다시 서명하고 최종 포장 파일을 새로 만들어야 합니다.
두 번째 단계: notarytool 로그에서 첫 번째 유효 오류 찾기
Invalid를 확인한 뒤에는 제출 ID로 정보와 로그를 받습니다. 자격 증명 값은 환경 변수나 안전한 비밀 저장소에서 읽고, 셸 기록과 CI 출력에 그대로 남기지 마십시오.
xcrun notarytool info <제출-ID> --keychain-profile <프로필-이름>
xcrun notarytool log <제출-ID> --keychain-profile <프로필-이름> \
--output-format json
명령의 실제 값은 문서와 자동화 환경에 맞게 넣어야 합니다. 로그는 마지막 문장보다 특정 경로가 포함된 첫 번째 유효 오류가 중요합니다. 같은 원인에서 파생된 후속 메시지를 먼저 고치면 불필요한 재서명이 이어질 수 있습니다.
대표적인 분기와 조치 범위는 다음과 같습니다.
- 서명이 유효하지 않음: 해당 경로의 실행 파일과 중첩 코드를 확인합니다. 외부 컨테이너만 다시 서명해 내부 오류를 가리지 마십시오.
- 안전한 타임스탬프가 없음: 배포용 서명 명령과 인증서 유형을 확인한 뒤 새 최종 파일을 만듭니다.
get-task-allow가 남아 있음: 개발용 권한이 배포 산출물에 섞였는지 Export와 서명 설정을 확인합니다.- 권한 형식이 잘못됨: 권한 파일의 문법과 실제 기능 요구를 비교합니다. 모르는 권한을 추가해 통과시키려 하지 마십시오.
- 인증서 유형이 맞지 않음: Mac App Store 경로와 Developer ID 직접 배포 경로를 구분합니다.
- 중첩 구성 요소가 누락됨: Framework, 플러그인, 보조 도구의 실제 위치와 서명 순서를 다시 확인합니다.
Apple의 공증 문제 해결 공식 문서는 오류별 증거와 수정 방향을 제공합니다. 제출이 오랫동안 처리 중이라면 로컬 스크립트만 반복하지 말고 Apple 시스템 상태도 확인해야 합니다. 일시적인 서비스 상황을 특정 오류의 일반 원인으로 단정해서는 안 됩니다.
세 번째 단계: 안쪽 코드부터 고치고 바깥 포장을 다시 만들기
재서명은 구조를 숨기는 명령이 아니라 구조를 확인한 뒤 수행하는 복구 단계입니다. 다음 순서를 지키십시오.
- 변경이 필요한 가장 안쪽 실행 파일을 확인합니다.
- Framework, 플러그인, 보조 도구처럼 안쪽에 포함된 코드를 먼저 수정하고 서명합니다.
- 앱 본체를 다시 서명합니다.
- 서명 결과를 검사한 뒤 ZIP, DMG 또는 PKG를 새로 만듭니다.
- 최종 포장 파일에 대해 제출과 공증을 다시 실행합니다.
재귀 서명만 실행하면 표면적인 결과는 좋아 보여도 어떤 구성 요소가 실제로 빠졌는지 알기 어려워집니다. 특히 설치 프로그램이 다른 실행 파일을 설치하는 경우에는 Apple의 Mac 소프트웨어 포장 안내에 맞춰 포장물의 역할과 제출 대상을 구분하십시오.
ZIP은 앱 디렉터리를 보존하는 배포용 포장물입니다. DMG는 사용자가 내려받는 디스크 이미지이며, PKG는 설치 프로그램입니다. 세 형식은 내부 구조와 배포 방식이 다르므로 하나를 고쳤다고 다른 형식까지 자동으로 검증된 것으로 보면 안 됩니다.
파일을 삭제하거나 인증서를 폐기하기 전에 현재 키체인과 프로파일을 백업하고, 이전 제출 파일을 보존하십시오. 자격 증명을 바꾸는 작업도 같은 원칙을 따릅니다. 새 인증 정보가 원격 세션에서 읽히지 않을 경우 기존 환경으로 되돌릴 수 있어야 합니다.
네 번째 단계: Accepted 이후 실제 사용자 경로를 검사하기
Accepted는 중요한 이정표지만 마지막 단계가 아닙니다. 서버가 제출물을 통과시켰다는 뜻과 사용자의 Mac이 파일을 허용한다는 뜻은 서로 다릅니다.
먼저 최종 파일에 티켓을 붙이고 검증합니다.
xcrun stapler staple <최종-앱-또는-배포물>
xcrun stapler validate <최종-앱-또는-배포물>
spctl --assess --type execute --verbose <최종-앱>
검사 대상은 작업 폴더의 임시 파일이 아니라 실제 다운로드 파일이어야 합니다. DMG를 배포한다면 DMG에서 복사한 앱을 검사하고, PKG라면 설치 후 생성된 앱을 검사하십시오. Apple의 공증 작업 흐름 공식 문서는 제출, 티켓 처리와 검증을 분리해 설명합니다.
개발 도구와 캐시가 남아 있는 Mac만 사용하면 문제가 가려질 수 있습니다. 별도의 사용자 환경에서 다시 내려받고, 가능한 경우 네트워크가 제한된 상태에서도 설치와 실행을 확인하십시오. 이 과정은 온라인 티켓에만 의존하는지, 최종 파일을 잘못 테스트하고 있는지 밝혀 줍니다.
이번 주에 원격 Mac 배포 흐름을 고정하는 조건
로컬에서는 되지만 원격 Mac에서 자동 공증이 실패한다면, 아래 조건으로 선택하십시오.
- Xcode 경로와 명령줄 도구가 고정되어 있으면 자동화 유지가 가능합니다. 경로가 세션마다 달라지면 먼저
DEVELOPER_DIR또는xcode-select를 고정하십시오. - 키체인 프로필이 비대화형 세션에서 읽히면 해당 인증 방식을 유지하십시오. 그래픽 로그인에만 의존하면 SSH 작업은 별도 복구가 필요합니다.
- 제출 ID, 최종 파일 해시, 로그가 한 작업 번호로 연결되면 원격 재시도를 허용하십시오. 연결이 없으면 자동 재제출을 중단하십시오.
- 작업에 대기 시간, 만료 시간, 재시도 횟수와 수동 중지 조건이 있으면 자동화를 운영할 수 있습니다. 조건이 없으면 같은 Invalid 파일을 계속 보낼 수 있습니다.
- 단절과 재부팅 뒤에도 로그와 비밀 정보가 안전하게 복원되면 상시 배포 환경으로 사용할 수 있습니다. 복원이 안 되면 정식 출시 전에 임시 버전으로 먼저 검증하십시오.
현재 개발 컴퓨터가 Developer ID 개인 키, Xcode 도구 체인과 장기 로그를 안정적으로 보관하지 못한다면, 원인 분석을 끝낸 뒤 권한을 분리한 상시 원격 Mac으로 서명·공증·Gatekeeper 검사를 옮기는 방법이 있습니다. VMSPIN의 원격 Mac 환경을 검토할 때도 먼저 비공식 버전으로 전체 배포 흐름을 재현하고, 이후 정식 버전에 적용하십시오.
FAQ
macOS 앱 공증 실패를 다룰 때 핵심은 재제출 횟수가 아닙니다. 어떤 파일이 어느 단계에서 실패했는지 보존하고, 최종 산출물을 기준으로 수정한 뒤, Accepted 이후 사용자 환경까지 검사하는 것이 핵심입니다.
현재 방식이 개인 Mac 한 대에만 의존한다면 키체인 세션, Xcode 경로, 디스크 상태와 로그 보존이 서로 얽히기 쉽습니다. 반대로 원격 Mac은 상시 환경을 만들 수 있지만 자격 증명 격리와 재부팅 복구를 직접 설계해야 합니다. 단기 테스트나 출시 직전 검증이라면 VMSPIN의 요금과 이용 방식을 확인한 뒤, 먼저 작은 배포물로 전체 흐름을 시험하는 편이 안전합니다. લાંબાաժամ?