Claude를 CI Co-pilot으로: Apple Signing Hell 디버깅, 당신은 직접 할 필요 없음

발행: (2026년 5월 8일 PM 05:02 GMT+9)
5 분 소요
원문: Dev.to

Source: Dev.to

문제 개요

이번 주에 나는 Apple 프로비저닝 오류 때문에 매 실행마다 실패하던 Fastlane CI 파이프라인을 몇 시간 디버깅했다. 디버깅 내내 Claude와 페어링했다. 아래는 깔끔하게 다듬어진 “AI가 코드를 도와줬다!” 이야기가 아니라, 실제 현장에서 일어난 어수선한 대화이다.

iOS 빌드 파이프라인은 Fastlane + match 를 사용해 코드 서명을 한다. CI 러너는 exportArchive 단계에서 다음과 같은 오류를 내며 폭발했다:

error: exportArchive: requires a provisioning profile with the App Groups feature

프로비저닝 프로파일에 App Groups 권한이 실제로 포함돼 있었음에도 (.mobileprovision 파일을 복호화해 확인) xcodebuild는 그렇지 않다고 주장했다.

근본 원인: Export Options 처리 오류

실패한 lane, gym이 생성한 임시 plist, 그리고 오류를 대화에 복사해 넣었다. Claude는 내가 놓친 부분을 찾아냈다:

  • Fastfile에서 export_optionsHash 로 전달하면 gym은 그 해시를 바로 임시 plist에 쓴다.
  • 해시 안에 plist: 키가 있으면 이는 파일 경로가 아니라 리터럴 값으로 처리된다.
  • 따라서 내가 로드하려던 외부 plist 파일은 실제로 로드되지 않았다.

잘못된 설정 (Hash 형태)

gym(
  export_options: {
    method: "app-store",
    plist: "RELEASE_exportOptionsPlist_Store.plist"
  }
)

수정된 설정 (경로 문자열)

gym(
  export_options: "RELEASE_exportOptionsPlist_Store.plist"
)

경로 문자열을 전달하면 gym이 외부 plist를 올바르게 로드하고, 런타임에 plist에 적용하려던 패치가 최종적으로 적용된다.

간헐적 실패: 동적 프로파일 이름

Export options를 고친 뒤에도 빌드는 간헐적으로 실패했다. 문제는 match 가 프로비저닝 프로파일을 갱신하면서 발생했다:

  • Apple은 프로파일 이름에 일련 번호 접미사를 붙인다 (예: match AppStore com.example.app 1777460891).
  • Fastfile, pbxproj, 그리고 export plist 모두 오래된 이름을 하드코딩하고 있었다.
  • 갱신이 일어나면 xcodebuild가 해당 프로파일을 찾지 못한다.

Claude는 match가 설정한 sigh_* 환경 변수를 통해 실제 설치된 프로파일 이름을 읽어온 뒤, 런타임에 pbxproj와 export plist를 모두 패치하자고 제안했다.

실제 프로파일 이름 읽어오기

profile_name = ENV["sigh_#{bundle_id}_appstore_profile-name"]

pbxproj 패치

sed -i '' "s/match AppStore #{bundle_id}.*/#{profile_name}/g" path/to/project.pbxproj

Export Plist 패치

/usr/libexec/PlistBuddy -c "Set :provisioningProfiles:#{bundle_id} #{profile_name}" ExportOptions.plist

정리

  • Gym API 미묘함: export_options를 해시로 전달하면 plist: 키가 무시된다; 외부 plist를 로드하려면 경로 문자열을 사용한다.
  • Match 환경 변수는 갱신 후 실제 프로파일 이름을 제공한다; 이를 이용해 설정을 동기화한다.
  • Claude와 페어 프로그래밍을 하면 Fastlane 전체 코드를 읽은 사람과 작업하는 느낌이 들어, 내부 툴체인의 동작을 빠르게 추론할 수 있었다.
  • 수정이 작동하는지를 이해하면 더 깔끔한 커밋과 정확한 커밋 메시지를 만들 수 있다 (예: Co-Authored-By: Claude Opus 4.7).
  • Claude는 마법이 아니다; 기존 지식을 증폭시켜준다. 코드 서명에 익숙하지 않다면 여전히 도메인을 학습해야 하지만, 디버깅 루프가 몇 시간에서 몇 분으로 크게 단축된다.

한때 부족한 트라이벌 지식이나 2019년 특정 Stack Overflow 답변에 의존해야 했던 복잡한 CI/CD 문제들이 이제는 한 세션만으로도 해결 가능해졌다. 이것이 진정한 잠금 해제 포인트다.

0 조회
Back to Blog

관련 글

더 보기 »