이 글이 하는 일
- Flutter iOS CI = 컨트롤 플레인 + 실행 플레인 + 캐시 플레인의 3계층 멘탈 모델 확립.
- macos-latest vs 자체 호스팅 결정 매트릭스 제공 — 5분 안에 결론.
- 심화 구현을 5개 주제 하위 글에 분배 — 고통 지점에서 바로 진입.
3계층 CI 모델
구체적인 도구를 보기 전에 하나의 방정식을 확립합니다 — 어떤 계층을 수정해야 하는지 결정합니다:
Flutter iOS CI =
컨트롤 플레인 (GitHub Actions: 트리거 · 승인 · Secrets 관리)
+ 실행 플레인 (Mac mini M4 : iOS 네이티브 빌드 · 서명 · 환경 일관성)
+ 캐시 플레인 (로컬 SSD : 의존성과 빌드 산출물의 영구 저장)
모든 결정을 좌우하는 세 가지 추론:
- 컨트롤 플레인은 코드를 실행하지 않습니다. workflow YAML을 최적화해도 빌드가 빨라지지 않습니다. 빌드 시간을 줄이려면 실행 플레인을 교체해야 합니다.
- 실행 플레인이 재현성을 결정합니다. 공유 풀(
macos-latest)의 Xcode 버전은 GitHub 업데이트에 따라 변합니다. 자체 호스팅 머신의 버전은 여러분이 고정합니다. - 캐시 플레인이 속도를 결정합니다. 자체 호스팅의 속도 이점은 CPU에서 오는 것이 아니라, 로컬 SSD가 작업별 원격 캐시 업로드/다운로드를 대체하는 데서 옵니다.
Flutter iOS CI에 전용 macOS 실행 플레인이 필요한 이유
Flutter는 Linux에서 Android 빌드와 단위 테스트를 처리할 수 있지만, iOS 빌드와 App Store 출시는 macOS에서만 실행 가능합니다 — Flutter의 문제가 아닌 Apple 툴체인의 하드 제약입니다.
따라서 모든 Flutter 팀은 아키텍처 선택에 직면합니다: iOS 실행은 어디서 할 것인가? macos-latest에서 벗어나게 만드는 세 가지 마찰:
- 비용: GitHub 호스팅 macOS Runner는 Linux 대비 분당 요금이 현저히 높습니다. iOS 콜드 빌드는 20~30분이 흔하고, 빌드 빈도가 높아지면 청구서가 빠르게 증가합니다.
- 환경 일관성: 호스팅 이미지의 Xcode 버전은 GitHub 업데이트에 따라 변하며 고정할 수 없습니다. "로컬은 통과, CI는 실패"가 반복되는 디버깅 비용이 발생합니다.
- 빌드 속도: iOS 의존성은 용량이 크고, 호스팅 Runner는 매 작업마다 캐시를 재업로드·재다운로드합니다. 로컬 SSD를 가진 자체 호스팅 머신은 이 병목을 근본적으로 제거합니다.
「macOS 실행 플레인을 제어 가능한 경계 내로 가져오기」— 이것이 이 아키텍처의 핵심 결정입니다. 컨트롤 플레인은 GitHub에 유지하고(PR 트리거, 리뷰 게이트, Secrets 관리), 실행 계층만 테넌트 전용 Mac mini M4로 교체합니다.
공식 참고자료: GitHub 자체 호스팅 Runner 문서 · Flutter CD 가이드
아키텍처 전체 개요
전체 파이프라인을 3계층 모델에 매핑합니다 — 문제 발생 시 먼저 어떤 플레인인지 파악하고, 해당 주제 글로 이동:
| 플레인 | 담당 | 비담당 | 장애 신호 |
|---|---|---|---|
| 컨트롤 플레인 | 트리거 규칙, 권한 경계, Secrets 주입, 산출물 업로드 | 빌드 코드 미실행 | Job 미트리거 / 권한 오류 / PR 게이트 오작동 |
| 실행 플레인 | iOS 네이티브 빌드, Xcode 버전 고정, 서명 체인 | 트리거 로직과 Secrets 출처 미관리 | 빌드 환경 드리프트 / 서명 실패 / Runner 오프라인 |
| 캐시 플레인 | 의존성과 빌드 산출물의 작업 간 영구화 | 빌드 트리거와 실행 환경 미결정 | 핫 빌드 ≈ 콜드 빌드 / 디스크 경고 / 무작위 실패 |
모든 Flutter iOS CI 장애는 이 세 행 중 하나에 매핑됩니다. 플레인을 올바르게 파악하면 수정 경로가 명확해집니다.
결정 매트릭스: 언제 마이그레이션이 가치 있는가?
자체 호스팅이 기본 답은 아닙니다. 5분 팀 리뷰에서 결론 내리기 위한 매트릭스:
| 신호 | macos-latest 유지 | 자체 호스팅 마이그레이션 |
|---|---|---|
| 빌드 빈도 | 월 40회 미만 iOS 빌드 | 월 40회 이상, 또는 매일 여러 번 |
| 환경 안정성 | Xcode 마이너 버전에 비민감 | Xcode / SDK 버전 고정 필요 |
| 빌드 속도 | 핫 빌드 8분 미만 허용 가능 | 핫 빌드가 지속적으로 8분 초과하여 이터레이션 영향 |
| 릴리스 파이프라인 | App Store 서명 불필요 | App Store / TestFlight 릴리스 파이프라인 보유 |
| 운영 의지 | 제로 운영 우선 | 월 1회 유지보수 창과 제어성 교환 수용 |
경험 법칙: 「마이그레이션」 신호 3개 이상 해당 시 — 자체 호스팅은 보통 2~4주 내에 비용을 회수합니다(머신 임대료 vs 절감된 호스팅 macOS 분 요금).
주제 시리즈: 고통 지점에서 바로 진입
이 글은 아키텍처 이해와 마이그레이션 결정만 다룹니다. 각 실행 계층의 심화 내용은 전용 주제 글에서:
| 주제 | 핵심 질문 | 플레인 | 링크 |
|---|---|---|---|
| ① Runner 구성 | Mac mini를 안정적으로 온라인 유지, 스케줄 가능, 안전하게 격리하는 방법 | 실행 | 출시 예정 |
| ② 3계층 캐시 모델 | iOS 빌드가 왜 빨라지지 않는지, 로컬 SSD로 해결하는 방법 | 캐시 | 출시 예정 |
| ③ 서명 및 릴리스 | 무인 CI에서 iOS 서명과 App Store 업로드를 완료하는 방법 | 실행 | 출시 예정 |
| ④ Workflow 설계 | Android/iOS 분리, 경로 필터링, 병렬성 제어 설계 방법 | 컨트롤 | 출시 예정 |
| ⑤ 운영 및 안정성 | CI가 왜 깨지는지, Runner 오프라인 복구, 디스크 꽉 참 방지 | 실행 + 캐시 | 출시 예정 |
시나리오별 진입 경로 선택
- 처음부터 구축: 이 글로 아키텍처 방향 확인 → ①「Runner 구성」으로 머신 온라인 → ②「캐시 모델」로 속도 튜닝 → ③「서명」으로 릴리스 파이프라인 연결.
- Runner는 있는데 iOS 빌드가 느림: ②「3계층 캐시 모델」로 바로 이동.
- 서명 또는 TestFlight가 막힘: ③「서명 및 릴리스」로 이동.
- Runner 오프라인 / 빌드 무작위 실패: ⑤「운영 및 안정성」으로 이동.
- Bitrise 등 클라우드 CI에서 마이그레이션: 이전 비용 비교표는 Bitrise vs 자체 호스팅 클라우드 Mac 결정 가이드 참고.
이 아키텍처를 실행할 Mac mini가 필요하신가요?
kvmboot는 테넌트 전용 Mac mini M4(16GB / 24GB)를 SSH/VNC를 통해 제공하며, 일/주/월 단위로 청구됩니다. 컨트롤 플레인은 GitHub에 유지하고, 실행 플레인만 이 머신으로 교체합니다. 이 글의 3계층 모델에 따르면, 일반적으로 Day 0에 프로비저닝, Day 1에 CI 파이프라인 연결, Day 2에 서명 검증이 이루어집니다. 첫 빌드부터 일관된 Xcode 버전으로 구축할 수 있습니다.