5분 내 개통

전용 macOS Runner
빌드 대기열과 작별

$21.2 / 일부터 · 베어메탈 머신 독점
지금 임대
완전한 Xcode SSH 접속

클라우드 Mac에서 Xcode CI/CD 구축: GitHub Actions·Jenkins 실전 가이드

iOS와 macOS 빌드 파이프라인은 실제 Apple 하드웨어에서만 실행할 수 있습니다. 이것이 GitHub Actions 공용 macOS Runner 대기가 30분 이상 걸리고, 팀이 고가 Mac Studio를 살 여유가 없는 근본 원인입니다. 본문은 SpinMac 클라우드 Mac mini M4 전용 노드에서 Xcode 환경 설정, 인증서 가져오기, Archive 서명, TestFlight 업로드, GitHub Actions와 Jenkins 전용 Runner로 마운트하는 전체 과정을 기록하고, 세 가지 일반적인 CI 방안의 적용 범위를 비교합니다.

iOS 빌드가 전용 macOS 환경을 떠날 수 없는 이유

Android는 Linux 컨테이너에서 Gradle을 실행할 수 있는 것과 달리, Apple의 빌드 도구체인. xcodebuild, 코드 서명, notarytool, App Store Connect API. 은 모두 macOS와 Apple Silicon / Intel 베어메탈 머신에 묶여 있습니다. iOS 제품을 보유한 모든 팀은 결국 「누가 이 Mac을 제공할 것인가」라는 문제에 직면하게 됩니다.

일반적인 고충은 세 가지로 정리할 수 있습니다: 공용 Runner 대기(GitHub Actions 무료 macOS 할당량이 부족해 피크 시간대 workflow가 20–45분 대기 후에야 머신을 할당받음), 로컬 개발 머신이 CI에 점유됨(동료가 push하면 Xcode 빌드 속도 급감, 팬 과열), 인증서와 키 관리 혼란(여러 머신에 각각 .p12를 가져와 만료 후 아무도 모름). 클라우드 전용 Mac 노드는 앞의 두 문제를 동시에 해결하고, 세 번째 문제에 단일 신뢰 환경을 제공합니다.

테스트 환경

하드웨어: Mac mini M4 · 10코어 CPU · 16 GB 통합 메모리 · 256 GB SSD · 1 Gbps 전용 대역폭(SpinMac 일본 노드).
시스템: macOS 15 Sequoia, Xcode 16.4. 프로젝트: SwiftUI 중형 앱(약 12만 줄, Extension target 3개 포함).
CI 도구: GitHub Actions self-hosted runner 2.323.0, Jenkins 2.479 LTS + macOS agent.
서명: Apple Distribution 인증서 + App Store Connect API Key(Issuer ID + Key ID + .p8).

세 가지 CI 방안 비교: 어떤 것을 선택할까?

Xcode를 설치하기 전에 팀이 어떤 경로에 있는지 먼저 파악하세요. 세 가지 방안에 절대적 우열은 없으며, 차이는 대기 허용도, 월간 빌드 횟수, 컴플라이언스 요구사항에 있습니다.

방안 일반적 비용 대기 / 동시 실행 적합한 팀
GitHub 호스팅 macOS Runner 분당 과금(약 $0.08/min부터) 공유 풀, 피크 시간 대기 현저 월 빌드 < 500분, 대기 허용 가능
Mac mini 자체 구매 후 서버실 배치 하드웨어 $599+ 일회성 + 전기·운영비 독점, 시스템·인증서 직접 유지보수 필요 고정 사무실 보유, 장기 고빈도 빌드
클라우드 전용 Mac(일 단위 임대) SpinMac $21.2/일부터, 계약 없음 베어메탈 머신 독점, 즉시 사용 가능 중소 팀, 단계적 릴리스, 원격 협업

실측 프로젝트에서 중형 SwiftUI 엔지니어링의 xcodebuild archive 전체 빌드는 M4 노드에서 약 4분 12초 소요(Swift 컴파일·링크 포함). 동일 프로젝트를 GitHub 호스팅 macOS-14 Runner에서 실행하면 18분 대기 후 실제 빌드 5분 40초. 총 소요 시간 약 24분. 「push 즉시 테스트」가 필요한 팀에게 대기 시간이 빌드 자체보다 배포 리듬에 더 큰 영향을 미치는 경우가 많습니다.

4m 12s M4 노드 Archive 소요 시간
18m GitHub 호스팅 대기(피크)
1–5 min SpinMac 노드 개통
16 GB 통합 메모리(swap 없음)

클라우드 노드 환경 초기화: Xcode와 서명 자료

SpinMac에서 제공하는 Mac mini는 완전한 macOS가 사전 설치되어 있으며 관리자 권한을 보유합니다. 개통 후 SSH 또는 브라우저 VNC로 로그인해 다음 순서로 CI 사전 설정을 완료하세요. 인증서와 프로비저닝 프로파일을 고정 경로에 집중 보관하고, 이후 workflow 스크립트에서 통일 참조하는 것을 권장합니다.

  1. 01
    Xcode 및 명령줄 도구 설치

    App Store 또는 xcode-select로 Xcode 16.x 설치, sudo xcodebuild -license acceptxcodebuild -runFirstLaunch 실행. 검증: xcodebuild -version이 올바른 버전 번호를 출력해야 합니다.

  2. 02
    서명 인증서 및 Provisioning Profile 가져오기

    Distribution .p12와 비밀번호를 보안 채널로 ~/certs/에 전송, security import로 키체인에 가져오기. .mobileprovision 파일은 ~/Library/MobileDevice/Provisioning Profiles/에 배치. CI 환경에서는 전용 키체인을 사용하고 -T /usr/bin/codesign 신뢰 설정을 권장합니다.

  3. 03
    App Store Connect API Key 설정

    Apple Developer 백엔드에서 API Key 생성, AuthKey_XXXXXX.p8~/private_keys/에 저장. TestFlight 업로드 시 xcrun altool 또는 fastlane pilot upload와 함께 사용해 대화형 Apple ID 로그인을 피하세요.

  4. 04
    저장소 클론 및 DerivedData 캐시

    최초 git clone 후 로컬 Archive를 한 번 실행해 서명 체인이 정상인지 확인. DerivedData를 로컬 SSD에 유지(256 GB는 중형 프로젝트에 충분), 이후 증분 빌드에서 30–50% 시간 절약 가능.

CI에서 키체인의 흔한 함정

헤드리스 환경(SSH / Runner)에서 codesign 실패의 90%는 키체인 미잠금 해제 또는 미인증입니다. 빌드 스크립트 시작 부분에 추가: security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db, set-key-partition-listcodesign의 개인키 접근 허용. 비밀번호를 Git 저장소에 평문으로 작성하지 마세요. GitHub Secrets 또는 Jenkins Credentials로 주입하세요.

GitHub Actions 자체 호스팅 Runner 마운트

전용 Runner 등록 후 workflow는 runs-on: self-hosted 또는 사용자 정의 label(예: macos-m4)로 이 클라우드 Mac에 지정해 공용 풀 대기를 완전히 우회할 수 있습니다. SpinMac 노드에서 실측 통과한 절차는 다음과 같습니다.

GitHub 저장소 Settings → Actions → Runners → New self-hosted runner에서 macOS ARM64 선택, 페이지 안내에 따라 actions-runner 패키지를 다운로드·압축 해제한 후 실행:

./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token RUNNER_TOKEN --labels macos-m4,ios-build --unattended

등록 완료 후 시스템 서비스로 설치해 노드 재시작 후 Runner가 자동 온라인되도록 설정: sudo ./svc.sh installsudo ./svc.sh start. workflow YAML에서 label 지정:

runs-on: [self-hosted, macos-m4]

일반적인 iOS 빌드 job 핵심 단계: 코드 체크아웃 → 키체인 잠금 해제 → xcodebuild archivexcodebuild -exportArchivexcrun altool --upload-app 또는 Fastlane upload_to_testflight. M4 노드에서 성공한 Fastlane lane은 push부터 TestFlight 처리 완료(Apple 측 대기 포함)까지 평균 약 11분, 로컬 빌드와 업로드는 6분대에 불과합니다.

보안 알림

자체 호스팅 Runner는 저장소 코드와 서명 키에 접근할 수 있으므로 반드시: 저장소 collaborator 권한 제한, Runner registration token 정기 교체, fork PR에서 키가 포함된 workflow 자동 트리거 금지(pull_request_target 사용 시 각별히 주의). 팀 공유 노드에서는 프로젝트별로 다른 Runner를 등록하거나 OpenClaw 샌드박스로 Agent 작업 범위를 격리할 수 있습니다.

Jenkins macOS Agent 설정 요점

팀에 Jenkins 컨트롤러가 이미 있다면(Linux에서 실행 가능), macOS 빌드 능력은 Agent 노드로 연결합니다. SpinMac 클라우드 Mac에 JDK 17과 Jenkins agent.jar를 설치하고 LaunchDaemon 방식으로 상주시키면, 컨트롤러가 SSH 또는 JNLP로 작업을 가져갑니다.

Jenkins의 장점은 파이프라인 시각화와 플러그인 생태계: Xcode 플러그인, Credentials Binding, AnsiColor 로그 색상, 빌드 산출물 아카이브 등. 일반적인 Pipeline 조각 로직: stage('Archive')에서 sh 'xcodebuild ...' 호출, stage('Upload')에서 Fastlane 또는 altool 호출. DEVELOPER_DIR/Applications/Xcode.app/Contents/Developer로 고정해 다중 Xcode 버전 전환 혼란을 방지하세요.

GitHub Actions와 비교하면 Jenkins는 다중 브랜치, 다중 환경, 수동 승인 게이트가 필요한 기업 내부 프로세스에 더 적합합니다. 클라우드 Mac 일 단위 임대는 「탄력적 Agent」로 활용 가능: 릴리스 주간에 노드 개통·Runner 마운트, 비수기에 해제, 연중 365일 서버실 Mac을 운영할 필요 없음.

Archive, 서명 및 TestFlight 업로드 실전

어떤 CI를 사용하든 최종 산출물 파이프라인은 동일: Archive로 .xcarchive 생성 → Export로 .ipa 생성 → App Store Connect 업로드. 명령줄 방식(Xcode GUI 비의존)이 CI의 표준입니다.

Archive 예시(Release 구성, scheme 및 출력 경로 지정):

xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -archivePath build/MyApp.xcarchive CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER="MyApp AppStore"

Export에는 ExportOptions.plist(method를 app-store로 설정)가 필요하며, 다음과 같이 실행:

xcodebuild -exportArchive -archivePath build/MyApp.xcarchive -exportPath build/export -exportOptionsPlist ExportOptions.plist

TestFlight 업로드는 API Key 방식을 권장해 무인 환경에서 이중 인증이 막히는 것을 방지:

xcrun altool --upload-app -f build/export/MyApp.ipa -t ios --apiKey KEY_ID --apiIssuer ISSUER_ID

중형 프로젝트에서 M4의 10코어 CPU는 Swift 동시 컴파일이 구형 Intel Mac CI 머신보다 눈에 띄게 빠릅니다. 16 GB 통합 메모리는 전체 clean build 시에도 여유가 있어 swap이 발생하지 않았습니다. Swift Package 의존성이 많다면 -clonedSourcePackagesDirPath 캐시 디렉터리를 활성화해 이후 빌드 시간을 단축하세요.

사무실 서버실 없이 iOS CI를 안정적으로 운영하려면?

많은 독립 개발자와 소규모 팀의 실제 곤경: macOS 빌드가 필요하지만 CI 전용 머신을 위해 사무실을 임대하고, 네트워크를 끌고, 정전·시스템 업그레이드를 처리하고 싶지 않음. 퍼블릭 클라우드 VM은 충족 불가(완전한 macOS와 Apple 서명 체인 없음), 중고 Mac mini를 집에 두면 업로드 대역폭 불안정, IP 변경, 가족의 실수로 전원 꺼짐 등의 문제.

SpinMac의 포지셔닝은 전용 베어메탈 Mac mini M4: 가상화 없음, 과매도 없음, 각 머신 16 GB 메모리와 1 Gbps 전용 대역폭, 결제 후 1–5분 내 자동 배포. 5개 리전(싱가포르, 일본(도쿄), 한국(서울), 중국 홍콩, 미국 동부)에서 타깃 사용자 분포에 따라 선택. 예: 일본 시장 대상 앱은 도쿄 노드로 TestFlight 업로드 시 국경 간 지연을 줄일 수 있습니다.

요금은 일 $21.2부터, 주 $57.3, 월 $106.1, 장기 계약 없음. 릴리스가 집중된 한 주에 노드를 개통해 Runner를 마운트하고, 일상 유지보수 기간에 해제하면 연중 자체 구매 머신+전기비보다 경제적인 경우가 많습니다. 다중 머신 병렬 빌드가 필요하면 Thunderbolt 5 병렬 연결 서비스로 80 Gbps 클러스터를 구성해, 대형 monorepo 또는 다중 앱 매트릭스 동시 Archive에 적합합니다.

  1. 01
    SpinMac에서 노드 선택 및 개통

    콘솔 로그인 후 지역·임대 기간 선택, 결제 후 SSH 자격 증명과 VNC 진입점이 자동 발급됩니다. 자세한 내용은 도움말 센터를 참조하세요.

  2. 02
    본문 3절에 따라 Xcode와 서명 설정 완료

    키체인과 API Key 경로를 환경 변수로 기록해 GitHub Actions / Jenkins에서 통일 읽기를 권장합니다.

  3. 03
    Runner 등록 및 최초 pipeline 트리거

    먼저 Debug 빌드를 통과시킨 후 Release Archive + TestFlight로 전환하고, Fastlane 또는 네이티브 스크립트를 저장소에 점진적으로 고정하세요.

비용과 선택: 한 표로 정리

귀하의 상황 권장 경로 클라우드 Mac 역할
독립 개발자, 월 1–2회 릴리스 릴리스일 SpinMac 일 단위 임대 + 수동 Archive 임시 빌드 머신, 사용 후 즉시 해제
5–15인 팀, 매일 다수 push 상주 self-hosted Runner 월 단위 임대, 독점·대기 없음
Jenkins 보유, macOS Agent 부재 클라우드 Mac을 탄력적 Agent로 피크 확장, 신규 구매 회피
다중 앱 매트릭스 + 야간 일괄 빌드 TB5 클러스터 병렬 연결 다수 M4 병렬 Archive

iOS CI/CD의 기술적 문턱은 Xcode 자체가 아니라 안정적인 macOS 연산력 + 재현 가능한 서명 환경에 있습니다. 공용 Runner는 저빈도 빌드에 적합하고, 자체 서버실은 운영 역량을 갖춘 성숙 팀에 적합하며, 클라우드 전용 Mac은 「대기 싫고, 머신 사기도 싫은」 중간 지대를 채웁니다. 일 단위 과금, 베어메탈 머신 성능 예측 가능, 글로벌 노드 근접 배포. 빌드와 서명을 클라우드로 옮기면 로컬 MacBook은 코드 작성에 집중할 수 있고, 한밤중 CI 작업에 팬과 메모리를 빼앗기지 않습니다.

베어메탈 머신 독점 · 5분 내 개통

iOS 프로젝트를 위한 대기 없는 macOS 빌드 머신

SpinMac Mac mini M4 전용 노드: 완전한 macOS와 Xcode, 16 GB 통합 메모리, SSH / VNC 접속, GitHub Actions·Jenkins Runner 마운트 가능, 일 $21.2부터.

$21.2 / 일부터
Apple M4
CPU10코어 독점
메모리16 GB 통합
대역폭1 Gbps 전용
SLA99.9%
개통1–5분