애플 공식 문서는 웹훅 전달 상태를 Success, Pending, Failed로 구분합니다. 공식 웹훅 관리 안내에 따라 설정하되, Webhook은 알림과 작업 시작에 사용하고 최종 판단은 서버 기록과 API 또는 화면으로 확인해야 합니다. 원격 맥이 빌드와 업로드를 담당하고, 서버가 이벤트 ID·버전·빌드 번호를 연결하는 구조가 가장 안전합니다.

이 글은 다음 사용자에게 맞습니다.

  • 업로드 뒤 처리 중, 실패, 완료 알림을 자동으로 받고 싶은 독립 개발자
  • 원격 맥의 빌드·업로드·콜백·재시도를 하나의 흐름으로 관리하는 운영자
  • 여러 사람이 같은 출시 상태를 확인해야 하는 소규모 팀

먼저 정할 것: 어떤 상태를 자동화할까

App Store Connect Webhooks를 연결하기 전에 “무엇을 알릴지”와 “무엇을 자동 실행할지”를 나눠야 합니다. 업로드가 끝났다는 사실과 TestFlight에서 실제로 테스트할 수 있다는 사실은 같지 않습니다.

애플의 이벤트 설명에 맞춰 다음처럼 분리하면 오판을 줄일 수 있습니다.

<
상태 영역확인하려는 결과권장 동작
빌드 업로드 상태바이너리가 애플 쪽으로 전달되었는지서버에 기록하고 운영자에게 알림
베타 빌드 상태TestFlight에서 테스트 가능한 상태인지API 또는 화면으로 재확인한 뒤 테스터 안내
앱 버전 상태심사 제출, 대기, 출시와 관련된 현재 단계자동 변경보다 사람의 확인을 우선
TestFlight 피드백테스터가 남긴 오류와 의견알림과 이슈 등록으로 연결
BUILD_UPLOAD_STATE_UPDATED 같은 이벤트는 흐름을 시작하는 신호입니다. 그러나 이벤트 하나만 보고 재업로드, 빌드 삭제, 출시 단계 변경을 실행하면 안 됩니다. 이벤트 ID, 앱 식별자, 버전 번호, 빌드 번호, 수신 시각을 함께 저장하고 같은 이벤트가 다시 들어와도 업무 동작은 한 번만 실행해야 합니다.

주의: “전송 성공”은 Transporter 또는 업로드 단계의 결과일 수 있습니다. 애플의 처리 완료와 TestFlight 사용 가능 여부는 별도로 확인해야 합니다. 빌드 상태의 의미는 [공식 빌드 업로드 상태 문서](https://developer.apple.com/help/app-store-connect/reference/app-uploads/build-upload-statuses?utm_source=openai)에서 확인합니다.

첫 단계: App Store Connect Webhooks를 설정하기

계정과 앱 범위를 먼저 확인합니다

App Store Connect의 Users and Access, Integrations, Webhooks 메뉴에서 사용할 팀과 앱 범위를 확인합니다. 계정 전체의 모든 앱을 자동으로 듣는다고 가정하지 말고, 설정 화면에서 선택한 앱 범위를 기록해 두어야 합니다.

여러 앱을 운영한다면 앱마다 웹훅을 따로 만들지, 하나의 수신 서버에서 앱 식별자로 분기할지 결정합니다. 이 선택은 이벤트 수신 방식보다 운영 권한과 장애 격리에 더 큰 영향을 줍니다.

수신 주소와 비밀값을 분리합니다

Payload URL은 외부에서 접근할 수 있어야 합니다. 수신 서버는 요청을 받은 즉시 원본 본문과 헤더를 보관하고 빠르게 응답해야 합니다. 긴 처리나 API 조회를 요청 수신 과정에 넣으면 네트워크 지연이 전달 실패로 이어질 수 있습니다.

설정에는 다음 값을 사용합니다.

  • Payload URL: https://<your-domain>/<webhook-path>
  • Secret: <WEBHOOK_SECRET>
  • 앱 식별자: <APP_ID>
  • 버전 번호: <VERSION>
  • 빌드 번호: <BUILD_NUMBER>
실제 비밀값, JWT, API 키, 완전한 콜백 주소는 문서나 로그에 남기지 않습니다. API 조회가 필요하다면 [App Store Connect API 키 생성 안내](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api?utm_source=openai)에 맞춰 별도 보관소에서 읽도록 구성합니다.

이벤트 선택은 운영 목적에 맞춥니다

처음부터 모든 이벤트를 받을 필요는 없습니다. 독립 개발자는 빌드 업로드와 베타 빌드 상태부터 시작하고, 팀 운영에서 앱 버전 상태와 TestFlight 피드백이 필요할 때 확장하는 편이 낫습니다.

공식 이벤트 유형 문서에 없는 유형을 추정해 자동화하지 마십시오. 애플이 공식적으로 제공하는 이벤트와 자체 시스템에서 추론한 상태를 구분해야 합니다.

두 번째 단계: 콜백을 받고 중복을 막기

수신 서버의 처리 순서는 다음과 같이 고정합니다.

  • 원본 요청 본문과 수신 시각을 먼저 저장합니다.
  • 요청의 출처와 서명 또는 비밀값 검증을 수행합니다.
  • 이벤트 ID가 이미 처리되었는지 조회합니다.
  • 이벤트 유형을 앱 식별자, 버전 번호, 빌드 번호와 연결합니다.
  • 업무 큐에 알림이나 후속 확인 작업을 등록합니다.
  • 처리 결과와 검증 실패 이유를 별도로 기록합니다.
이벤트 ID가 이미 성공 처리되었다면 같은 알림을 다시 보내지 않습니다. 반대로 이벤트 ID가 새롭지만 앱이나 빌드 번호를 연결하지 못하면 자동 배포로 넘기지 말고 API 또는 App Store Connect 화면에서 확인 대기 상태로 전환합니다. <
검증 항목통과할 때실패할 때
이벤트 ID새 업무 기록 생성기존 결과만 반환
앱 식별자대상 앱과 연결수동 확인 대기
버전·빌드 번호원격 맥 작업과 연결업로드 기록과 대조
이벤트 상태알림 또는 확인 작업 실행자동 배포 중단
원본 요청감사 로그에 보관접근 로그와 함께 격리
App Store Connect Webhooks는 “현재 최종 상태를 항상 알려 주는 데이터베이스”가 아닙니다. 이벤트를 받은 뒤 필요한 경우 [빌드 상태 공식 참고 문서](https://developer.apple.com/help/app-store-connect/reference/app-uploads/app-build-statuses?utm_source=openai)와 API를 사용해 현재 값을 조회해야 합니다.

세 번째 단계: 원격 맥의 업로드를 상태 흐름에 연결하기

원격 맥에서 수행하는 작업을 하나의 성공으로 묶지 마십시오. 다음 단계는 서로 다른 실패 원인을 가집니다.

Archive 시작 → Export 완료 → 바이너리 업로드 → 애플 처리 중 → 처리 완료 또는 실패 → TestFlight 확인 가능

따라서 내부 상태도 이 흐름에 맞춰 나누는 것이 좋습니다.

  • started: 아카이브 작업이 시작됨
  • uploaded: 바이너리 전송이 끝남
  • processing: 애플 처리를 기다림
  • processed: 빌드 상태를 다시 확인함
  • failed: 업로드나 처리 실패
  • manual_review: 자동 연결 또는 상태 확인이 불가능함
이 구조라면 원격 맥에서 전송이 끝났다는 알림이 왔을 때 곧바로 “TestFlight 배포 완료”라고 표시하지 않습니다. 서버는 버전 번호와 빌드 번호를 이용해 해당 업로드를 찾고, 조회 결과가 일치할 때만 다음 상태로 이동시킵니다.

App Store Connect Webhooks로 빌드 업로드 완료 알림을 받는 방법을 찾는 경우에도 같은 원칙을 적용해야 합니다. 웹훅 수신은 시작 신호이고, 실제 완료 판정은 연결된 빌드 상태 조회가 담당합니다.

네 번째 단계: 실패한 전달과 중복 알림을 복구하기

웹훅 전달이 Pending 또는 Failed가 되면 먼저 수신 서버의 네트워크와 응답 기록을 확인합니다. 일시적인 네트워크 오류나 서버 오류는 재시도 대상이 될 수 있지만, 잘못된 서명, 누락된 앱 연결, 유효하지 않은 바이너리 같은 업무 오류는 같은 요청을 반복해도 해결되지 않습니다.

애플은 웹훅 관리 화면에서 최근 전달 기록과 이벤트 상세 내용을 확인하고, 일부 전달을 다시 보낼 수 있도록 안내합니다. 공식 관리 문서의 재전송 기능을 사용하더라도 서버의 멱등 처리는 그대로 유지해야 합니다.

복구 순서는 다음과 같습니다.

  • 전달 상세에서 이벤트 ID와 실패 원인을 확인합니다.
  • 수신 서버가 원본 요청을 저장했는지 확인합니다.
  • 네트워크 또는 임시 서버 오류인지 업무 오류인지 분류합니다.
  • 복구 가능한 오류만 전달 재시도를 사용합니다.
  • 이벤트를 다시 받아도 기존 업무 동작이 중복되지 않는지 확인합니다.
  • 최종 빌드 상태는 API나 App Store Connect 화면으로 확인합니다.

경험상 가장 위험한 자동화는 “콜백을 받으면 다시 업로드한다”는 규칙입니다. 업로드는 이미 끝났지만 처리만 지연된 경우 중복 빌드와 혼란스러운 출시 기록을 만들 수 있으므로, 재업로드는 사람이 실패 원인을 확인한 뒤 결정해야 합니다.

다섯 번째 단계: 첫 실제 출시로 검증하기

처음부터 운영 앱 전체에 적용하지 말고, 한 번의 탈감작된 테스트 빌드로 아래 흐름을 검증합니다.

  • 원격 맥의 아카이브와 내보내기 로그가 남는지 확인합니다.
  • 업로드 결과와 이벤트 ID를 같은 작업 기록에 연결합니다.
  • 앱 식별자, 버전 번호, 빌드 번호가 서로 일치하는지 확인합니다.
  • 처리 중 상태가 즉시 완료로 바뀌지 않는지 확인합니다.
  • 동일 이벤트 재전송이 업무 동작을 한 번만 만드는지 확인합니다.
  • 전달 실패 뒤 재시도와 수동 확인이 가능한지 확인합니다.
  • 로그에서 Secret, JWT, API 키와 전체 Payload가 노출되지 않는지 점검합니다.
  • 서버 기록과 App Store Connect 화면의 최종 상태가 일치하는지 대조합니다.
이 검증을 통과하면 팀 알림을 붙일 수 있습니다. 다만 알림은 상태 기록을 대신하지 않습니다. 메일 알림을 유지할지, API 조회를 보조 수단으로 둘지는 장애 시 누가 최종 판단을 맡는지에 따라 정해야 합니다.

장기 운영: API와 원격 맥의 역할을 나누기

App Store Connect Webhooks는 API와 함께 사용하는 편이 좋습니다. 웹훅만 사용하면 전달 실패나 순서 뒤바뀜을 보정하기 어렵고, API만 주기적으로 조회하면 불필요한 요청과 지연이 생깁니다.

<
구성장점한계적합한 경우
웹훅만 사용이벤트를 빠르게 감지누락·중복·최종 상태 보정이 약함단순 알림
API만 사용현재 상태를 직접 확인계속 조회하는 운영 부담보정 조회
웹훅과 API 조합이벤트 감지와 최종 확인을 분리서버와 기록 설계가 필요함지속 출시와 팀 운영
원격 맥에서 화면을 계속 확인초기 구성이 쉬움세션 종료, 권한, 화면 상태에 취약함임시 수동 작업
원격 맥 업로드 뒤 TestFlight 상태를 자동으로 판단하려면 웹훅을 받은 서버가 먼저 빌드 번호를 찾고, 그 결과를 API 또는 화면으로 다시 확인해야 합니다. 원격 맥에 페이지 폴링을 맡기면 화면 세션이 끊겼을 때 상태가 사라질 수 있습니다.

상시 빌드와 업로드를 맡길 별도 환경이 없다면 MACGPU의 원격 맥 환경을 검토할 수 있습니다. 다만 이미 안정적인 자체 빌드 머신이 있고 물리 장비 접근이나 장기 고정 부하가 필요하다면 직접 구매하거나 기존 인프라를 유지하는 편이 더 적합할 수 있습니다.

마무리: 상태 감시는 서버에, 실행은 원격 맥에

이 구성에서 가장 중요한 경계는 간단합니다. 원격 맥은 아카이브와 업로드를 실행하고, Webhook은 변화를 알리며, 서버는 이벤트를 저장하고, API 또는 App Store Connect 화면은 최종 상태를 확인합니다.

로컬 맥만으로 운영하면 장비가 꺼졌을 때 업로드가 멈추고, 화면 폴링은 세션 단절과 오판에 취약하며, 별도 빌드 서버를 직접 관리하면 권한·디스크·업데이트·복구 작업이 계속 발생합니다. 이런 부담 때문에 상시 실행되는 macOS 환경이 필요하지만 장비를 바로 구매하고 싶지 않다면, MACGPU의 맥 대여 구성을 확인해 볼 수 있습니다. 단기 출시 검증이나 지속적인 원격 맥 업로드처럼 사용 기간이 분명한 경우에 특히 현실적인 선택입니다.