fastlane match 원격 맥 서명: 2026 가이드
Apple은 프로비저닝 프로파일이 서명 주체, 앱 식별자, 인증서, 권한을 함께 검증하는 구조라고 설명합니다. 따라서 fastlane match 원격 맥 서명은 인증서 파일을 가져오는 것만으로 끝나지 않습니다. 원격 CI에서는 readonly 동기화, 임시 또는 격리 키체인, 명시적 프로파일 매핑, 빌드 후 정리를 함께 적용해야 합니다. (Apple 프로비저닝 프로파일 공식 문서)
이 글은 원격 노드에서 iOS 또는 macOS 앱을 서명·아카이브·배포하는 DevOps 엔지니어를 대상으로 합니다. 여러 앱과 Extension을 하나의 맥 Runner에서 운영하거나, 로컬 fastlane 흐름을 장기 실행 환경으로 옮기는 개발자에게 적합합니다.
먼저 결정할 원격 서명 운영 조건
다음 조건에서 3개 이상 해당하면 작업 전용 키체인과 명시적 프로파일 매핑을 선택하는 편이 안전합니다.
- [ ] 하나의 원격 맥에서 여러 앱을 빌드합니다.
- [ ] Widget 또는 Notification Service Extension을 함께 배포합니다.
- [ ] 서로 다른 Apple Team이 같은 Runner를 사용합니다.
- [ ] Runner가 재시작된 뒤에도 자동으로 빌드되어야 합니다.
- [ ] 인증서와 프로파일을 CI에서 새로 만들지 않고 관리 환경에서만 갱신합니다.
- [ ] 실패한 빌드 뒤에도 다음 작업이 깨끗한 상태에서 시작되어야 합니다.
- [ ] 병렬 작업이 서로 다른 서명 자산을 사용해야 합니다.
판단은 다음처럼 나눌 수 있습니다.
- 단일 앱, 단일 Team, 일회성 노드라면
readonly동기화와 기본 검증으로 시작할 수 있습니다. - 여러 Target 또는 여러 Team이라면 Bundle ID별 프로파일을 명시하고 작업별 키체인을 분리합니다.
- 장기 실행 Runner라면 재시작, 연속 작업, 실패 복구 테스트를 통과하기 전에는 운영 노드로 사용하지 않습니다.
- 인증서 만료나 폐기 직후라면 저장소 초기화보다 자산 상태 확인과 백업을 먼저 실행합니다.
로컬 성공과 원격 CI 실패를 가르는 네 가지 경계
로컬에서 서명이 성공했다는 사실은 원격 CI의 재현성을 보장하지 않습니다. 두 환경에서 다음 네 가지가 자주 달라집니다.
- 서명 인증서와 개인 키: 인증서 파일만 있고 개인 키가 없으면 서명 신원을 사용할 수 없습니다. Apple의 키체인 서비스는 인증서와 암호화 키를 키체인에 저장합니다. (Apple 키체인 서비스 공식 문서)
- 프로비저닝 프로파일: 프로파일은 Bundle ID, Team, 인증서와 연결됩니다. 메인 앱과 Widget Extension은 서로 다른 Bundle ID를 가지므로 같은 프로파일을 재사용할 수 없습니다.
- 키체인 세션: 대화형 로그인에서는 키체인이 이미 잠금 해제되어 있을 수 있습니다. 백그라운드 Runner에서는 같은 개인 키가 있어도 접근 권한 때문에 실패할 수 있습니다.
- Xcode 프로젝트 설정:
CODE_SIGN_STYLE,CODE_SIGN_IDENTITY,PROVISIONING_PROFILE_SPECIFIER가 환경마다 다르면 자동 서명이 다른 자산을 고를 수 있습니다. Apple은 수동 서명에서 개발자가 프로파일과 인증서를 직접 관리한다고 설명합니다. (Xcode 빌드 설정 공식 문서)
로그에서는 단순히 “빌드 실패”만 기록하지 않습니다. 인증서, 개인 키, 프로파일, 빌드 설정을 분리해 확인해야 합니다. 암호, MATCH_PASSWORD, 저장소 토큰, App Store Connect 인증 정보는 로그에 남기면 안 됩니다.
단일 앱에서는 동기화와 빌드를 분리합니다
단일 App Store 배포의 최소 구성은 세 단계입니다.
setup_ci: CI 전용 키체인과 로그 수집 환경을 준비합니다.match: 암호화 저장소에서 인증서와 프로파일을 읽어옵니다.build_app: Xcode 아카이브와 내보내기를 실행합니다.
fastlane 공식 문서는 setup_ci가 임시 키체인을 만들 수 있다고 설명합니다. CI에서 match를 실행할 때는 새 자산을 생성하지 않도록 readonly를 사용하는 구성이 일반적으로 적합합니다. (fastlane match 공식 문서)
platform :ios do
lane :release do
setup_ci if ENV["CI"]
match(
type: "appstore",
readonly: true,
app_identifier: "com.example.app"
)
build_app(
scheme: "Example",
workspace: "Example.xcworkspace",
export_method: "app-store"
)
end
end
환경 변수는 코드에 직접 쓰지 않습니다.
MATCH_PASSWORD=<CI_SECRET>
MATCH_GIT_URL=<PRIVATE_SIGNING_REPOSITORY>
LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
fastlane CI 문서는 MATCH_PASSWORD, Apple 서비스 접근 정보, UTF-8 로케일 설정을 주요 환경 변수로 제시합니다. 실제 변수 이름과 인증 방식은 사용하는 저장소와 CI 플랫폼의 공식 문서를 기준으로 확인해야 합니다. (fastlane CI 공식 문서)
빌드가 끝난 뒤에는 lane의 성공 여부만 확인하지 않습니다.
security find-identity -v -p codesigning
정상적인 출력에는 유효한 코드 서명 신원 수와 인증서 이름이 표시됩니다.
1) ABCDEF1234567890 "Apple Distribution: Example Team (ABCDE12345)"
1 valid identities found
이 출력은 프로파일이 올바르다는 뜻은 아닙니다. 아카이브와 내보낸 결과물을 별도로 확인해야 합니다.
여러 Target에서는 자동 선택보다 명시적 매핑을 우선합니다
메인 앱, Widget, Notification Service Extension이 함께 있는 프로젝트에서는 fastlane match 호출만으로 충분하지 않을 수 있습니다. 각 Target의 Bundle ID와 배포 프로파일을 연결해야 합니다.
match(
type: "appstore",
readonly: true,
app_identifier: [
"com.example.app",
"com.example.app.widget",
"com.example.app.notification"
]
)
build_app(
scheme: "Example",
export_method: "app-store",
export_options: {
provisioningProfiles: {
"com.example.app" => "match AppStore com.example.app",
"com.example.app.widget" => "match AppStore com.example.app.widget",
"com.example.app.notification" => "match AppStore com.example.app.notification"
}
}
)
build_app 공식 문서는 프로파일을 자동으로 찾지 못할 때 Bundle ID와 프로파일 이름을 provisioningProfiles로 직접 매핑할 수 있다고 설명합니다. (fastlane build_app 공식 문서)
역할은 다음처럼 분리합니다.
- Matchfile: 저장소 위치, Team 식별자, 공통 동기화 설정을 보관합니다.
- Fastfile: 배포 환경별
type,app_identifier,readonly정책을 보관합니다. - Xcode Build Settings: Target별 서명 방식과 빌드 구성을 보관합니다.
- Export 설정: 아카이브를 어떤 배포 방식으로 내보낼지와 프로파일 매핑을 보관합니다.
검증 순서는 다음과 같습니다.
security find-identity -v -p codesigning으로 인증서와 개인 키를 확인합니다.- 각 프로파일의 Bundle ID와 Team ID를 확인합니다.
.xcarchive내부의 앱과 Extension 목록을 확인합니다.codesign -d --entitlements :-로 서명된 권한을 출력합니다.- 최종
ipa가 예상한 앱과 Extension을 포함하는지 확인합니다.
Apple은 프로비저닝 프로파일의 권한 목록이 앱이 주장하는 권한을 허용하는 목록으로 작동한다고 설명합니다. 앱이 요구하는 권한과 프로파일의 권한이 다르면 인증서가 정상이어도 내보내기 또는 실행 단계에서 실패할 수 있습니다. (Apple 코드 서명 기술 문서)
주의: 자동 서명은 개발자 테스트에는 편리하지만, 배포 CI의 감사 가능성을 낮출 수 있습니다. 배포 lane에서는 Bundle ID와 프로파일의 연결 관계를 설정 파일과 로그로 남겨야 합니다.
여러 Team이 같은 원격 맥을 사용할 때는 경계를 나눕니다
여러 Apple Team이나 여러 앱이 하나의 원격 맥을 공유하면 기존 자산이 새 작업에 섞일 수 있습니다. 로그인 키체인에 이전 Team의 인증서가 남아 있으면 Xcode가 예상과 다른 서명 신원을 선택할 가능성도 있습니다.
운영 단위는 최소한 다음처럼 나누는 편이 안전합니다.
- Team별 서명 저장소 또는 저장소 브랜치
- 앱과 배포 환경별
app_identifier - CI 저장소에 대한 읽기 전용 접근 정보
- 작업별 임시 키체인
- Runner 라벨과 저장소 접근 그룹
GitHub Actions를 사용하는 경우 여러 라벨을 조합해 특정 노드로 작업을 보낼 수 있습니다. GitHub 공식 문서는 여러 라벨을 모두 만족하는 Runner에 작업이 배정된다고 설명합니다. (GitHub 자체 호스팅 Runner 공식 문서)
jobs:
release:
runs-on: [self-hosted, macOS, ARM64, ios-release]
steps:
- uses: actions/checkout@v6
- run: bundle install
- run: bundle exec fastlane release
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
공개 저장소의 포크가 자체 Runner에서 코드를 실행하지 못하도록 접근 정책도 제한해야 합니다. GitHub는 작업 코드가 자체 호스팅 Runner의 로컬 자산에 접근할 수 있다는 점을 경고합니다. (GitHub 자체 호스팅 Runner 보안 문서)
장기 실행 Runner는 임시 환경처럼 검증합니다
장기 실행 원격 맥은 한 번 설정하고 방치하는 서버가 아닙니다. 작업이 실패한 뒤 남은 프로파일, 아카이브, 키체인이 다음 빌드에 영향을 줄 수 있습니다.
security list-keychains
security find-identity -v -p codesigning
find "$HOME/Library/MobileDevice/Provisioning Profiles" \
-type f -maxdepth 1 -print
CI 작업의 종료 단계에서는 다음 항목을 정리합니다.
- 작업 전용 키체인 잠금 또는 삭제
- 임시 프로파일 삭제
- 빌드와 아카이브 임시 디렉터리 삭제
- 로그 내 토큰과 암호 마스킹 여부 확인
- 실패 작업의 체크아웃 디렉터리 제거
- 작업 종료 후 Runner 상태 확인
운영 방식 선택 조건
- 일회성 Runner: 작업이 끝나면 호스트 자체를 폐기할 수 있습니다. 잔류 자산 관리 부담은 작지만 매번 개발 도구와 서명 자산을 준비해야 합니다.
- 장기 원격 맥 Runner: 의존성과 캐시를 유지하기 쉽습니다. 대신 키체인 오염, 프로파일 충돌, 사용자 세션, 동시 작업을 직접 관리해야 합니다.
- 공유 로그인 키체인: 초기 설정은 빠르지만 여러 Team의 인증서가 섞이고 삭제 책임이 불명확합니다.
- 작업 전용 임시 키체인: 초기 설정은 더 필요하지만 작업 경계와 정리 시점을 분명하게 만들 수 있습니다.
다음 조건 목록에서 하나라도 해당하면 공유 로그인 키체인 대신 작업 전용 키체인을 사용합니다.
- [ ] 서로 다른 앱의 배포 작업이 같은 사용자 계정에서 실행됩니다.
- [ ] 같은 맥에서 병렬 또는 예약 작업이 실행됩니다.
- [ ] 인증서 접근 권한을 작업 단위로 제한해야 합니다.
- [ ] 실패 후 다음 작업이 자동으로 재시작됩니다.
- [ ] 노드 재구축을 정기적으로 수행할 수 있습니다.
반대로 단일 앱과 단일 Team만 사용하고, 작업마다 노드를 초기화할 수 있다면 단순한 운영 구성이 가능합니다. 그래도 security find-identity와 프로파일 목록 검사는 매번 실행해야 합니다.
FAQ
fastlane match를 원격 맥의 키체인에 어떻게 넣어야 하나요?
CI에서는 로그인 키체인에 장기간 인증서를 쌓기보다 setup_ci가 만드는 임시 키체인을 우선 사용합니다. match를 실행한 뒤 security find-identity로 유효한 서명 신원을 확인하고, 빌드가 끝나면 임시 키체인과 내려받은 프로파일을 제거합니다. 장기 Runner라면 재시작 뒤에도 같은 절차가 반복되는지 확인해야 합니다.
로컬에서는 fastlane match가 되는데 CI에서는 왜 서명이 실패하나요?
로컬 환경에는 이미 개인 키, 프로파일, 잠금 해제된 키체인, Xcode 계정 상태가 남아 있을 수 있습니다. 반면 CI는 다른 사용자 세션이나 잠긴 키체인에서 시작합니다. 인증서만 가져오는 방식으로는 부족합니다. 키체인 접근 권한, Bundle ID별 프로파일, CODE_SIGN_STYLE과 export 설정을 함께 기록하고 검증해야 합니다.
원격 맥 CI에서 match는 readonly로 실행해야 하나요?
배포 CI에서는 대부분 readonly가 적합합니다. fastlane 공식 문서도 CI에서 새 인증서나 프로파일을 만들지 않도록 readonly 사용을 권장합니다. 자산을 갱신하는 작업은 별도의 승인된 관리 환경에서 실행하고, CI는 암호화 저장소에 이미 등록된 자산만 동기화해야 합니다. 그래야 병렬 작업이 서로 다른 자산을 만들지 않습니다.
여러 타깃의 프로비저닝 프로파일은 어떻게 나누나요?
메인 앱과 Extension은 Bundle ID가 다르므로 프로파일도 별도로 매핑해야 합니다. match의 app_identifier에 필요한 식별자를 명시하고, build_app의 export_options에서 Bundle ID와 프로파일 이름을 연결합니다. Xcode의 자동 서명에 의존하면 환경에 따라 다른 프로파일이 선택될 수 있으므로 배포용 설정은 명시적으로 고정하는 편이 안전합니다.
항상 켜 둔 맥 Runner에서 서명 인증서와 키체인은 어떻게 정리하나요?
작업 전용 키체인을 만들고 작업이 끝난 뒤 잠그거나 삭제하는 방식이 기본입니다. 저장소에서 내려받은 프로파일, 임시 아카이브, 로그에 포함된 비밀값도 함께 점검해야 합니다. 재시작 후 첫 작업, 연속 작업, 실패 후 정리 작업을 각각 실행해 잔류 자산이 다음 앱의 서명에 영향을 주지 않는지 확인합니다.
인증서 만료와 노드 재구축은 복구 순서를 지켜야 합니다
인증서가 만료되었거나 폐기되었을 때 곧바로 저장소를 초기화하면 영향 범위가 커집니다. 먼저 현재 자산의 상태와 사용 중인 배포 채널을 확인해야 합니다.
권장 복구 순서는 다음과 같습니다.
- Apple Developer 계정에서 인증서와 프로파일의 상태를 확인합니다.
- 현재 배포 중인 앱과 Team에 영향을 주는 자산을 목록화합니다.
- 정상 자산의 암호화 저장소와 변경 기록을 백업합니다.
- 승인된 관리 환경에서 새 인증서 또는 프로파일을 생성합니다.
match저장소를 갱신합니다.- 원격 맥에서
readonly동기화를 실행합니다. - 모든 Target을 다시 아카이브합니다.
codesign, 프로파일, 최종ipa를 검증합니다.- 이전 인증서와 자격 증명이 더 이상 사용되지 않는지 확인합니다.
- 노드 재구축과 롤백 결과를 기록합니다.
match nuke와 같은 파괴적 초기화 명령은 일반적인 오류 해결책으로 사용하지 않아야 합니다. 기존 배포 앱, 다른 팀원, 테스트 기기, 자동화 파이프라인에 영향을 줄 수 있기 때문입니다. 기존 자산의 백업과 승인 절차가 있을 때만 제한된 범위에서 실행해야 합니다. (fastlane match 명령 공식 문서)
노드 재구축 테스트는 다음 세 가지로 나눕니다.
- 재시작 테스트: 맥을 재시작한 뒤 첫 CI 작업이 대화형 로그인 없이 서명되는지 확인합니다.
- 연속 작업 테스트: 서로 다른 앱 또는 Target을 연속으로 빌드해 이전 프로파일이 재사용되지 않는지 확인합니다.
- 실패 복구 테스트: 잘못된 프로파일을 사용한 뒤 정리 단계가 실행되고, 다음 정상 작업이 성공하는지 확인합니다.
SFTPMAC의 원격 맥 대여 요금 안내를 검토할 때도 단순한 접속 가능 여부보다 root 권한, 재시작 권한, 키체인 정리 가능 여부, 장기 Runner 운영 조건을 먼저 확인하는 편이 낫습니다. 개발 환경을 다른 지역 노드와 비교해야 한다면 서울 맥 미니 대여 환경처럼 실제 사용 지역과 연결 경로가 드러나는 조건을 기준으로 판단해야 합니다.
원격 맥을 선택할 조건과 선택하지 않을 조건
현재 노트북이나 Linux 서버에서 서명을 처리하는 방식은 초기 비용이 들지 않는다는 장점이 있습니다. 그러나 macOS 전용 Xcode 도구를 직접 실행할 수 없고, 별도 맥을 개인 장비로 연결하면 전원, 네트워크, 재부팅, 키체인 잠금, 저장 공간을 계속 관리해야 합니다. 가상 macOS 환경은 하드웨어와 라이선스 조건, 장치 접근, Xcode 버전 호환성까지 추가로 검토해야 합니다.
반대로 장기적으로 매일 무거운 빌드를 실행하고 물리 장치 연결이나 내부 네트워크 장비가 필요하다면 자체 Mac mini가 더 적합할 수 있습니다. 하지만 한 번의 마이그레이션, 특정 인증서 교체, 단기 릴리스 기간, 새로운 CI 구조 검증이 목적이라면 실물 장비를 바로 구매할 필요는 없습니다.
서명 흐름을 설계한 뒤에는 root 권한이 있는 원격 맥에서 재시작과 노드 재구축 테스트를 먼저 진행하는 편이 안전합니다. SFTPMAC의 macOS 원격 환경을 이용하면 필요한 기간 동안 실제 맥 노드에서 fastlane match, Xcode 아카이브, 키체인 정리 절차를 검증할 수 있습니다.