들어가며
센디 iOS 앱은 제가 혼자 맡아 개발합니다. 팀에서 iOS 빌드와 배포를 맡는 사람도 저뿐입니다. 별도 QA 조직은 없고, 엔지니어가 개발 단계에서 1차로 확인한 뒤 PM과 디자이너에게 공유합니다. 그 공유용 빌드를 다시 만들어 넘기는 일도 전부 제 몫이었습니다.
문제는 그 공유가 자주, 짧은 간격으로 온다는 점이었습니다. 피드백을 반영하고 다시 빌드하고 다시 받아 보는 일을 반복할수록 내부 확인용 빌드를 새로 뽑는 횟수가 늘었습니다. 그때마다 Xcode에서 Archive가 끝나기를 기다렸고, 팀에 적어 둔 Staging 배포 기준으로는 한 번 archive를 시작하면 평균 20분 정도가 그대로 지나갔습니다.
이 글은 그 수동 배포를 어떤 순서로 걷어냈는지 정리한 기록입니다. 먼저 배포 시작을 GitHub Actions로 옮긴 이유와 워크플로 구성을 보고, 그다음 자동화 이후에 드러난 빌드 반복 대기를 CocoaPods 캐시와 ccache로 어떻게 줄였는지를 다룹니다.
숫자 축만 먼저 밝힙니다. archive 약 20분(로컬 Staging 기준), CI 한 실행 12분대, ccache 6분→4분(로컬)은 서로 다른 구간입니다. 전/후로 묶지 않습니다.
센디 플랫폼 스쿼드가 일하는 방식
센디 제품 개발은 스쿼드 단위로 돌아갑니다. 저는 그중 플랫폼 스쿼드에 붙어 iOS를 맡습니다. 랜딩부터 오더와 결제까지 전환 퍼널을 다루는 스쿼드고, PM과 디자이너, 서버, 클라이언트(안드로이드와 iOS)가 같은 목표를 봅니다.
스토어까지 가는 확인은 대략 세 구간입니다. 여기서 말하는 건 누가 무엇을 확인하느냐이지, 아직 git 브랜치 이름이 아닙니다.
기능 확인
스쿼드가 목표에 맞는 피처를 기획하고 개발합니다. 엔지니어가 1차로 확인한 뒤, 필요할 때 PM과 디자이너에게 빌드를 공유하고 피드백을 반영합니다. 이 단계에서의 공유도 Firebase App Distribution으로 합니다. 개발 → 빌드 → 공유 → 피드백 → 수정 → 개발 사이클이 빠르게 반복됩니다.
내부 확인
피처가 어느 정도 모이면 내부용 빌드로 다시 확인합니다. Staging 환경에 올린 앱을 Firebase App Distribution 링크로 나눠 주고, 스쿼드 안에서 다시 테스트와 수정을 돌립니다.
스토어 직전 확인
내부 확인이 끝나면 Production 빌드를 TestFlight에 올려 최종 확인합니다. 여기서 막히지 않으면 스토어 제출로 이어집니다.
세 구간 모두에서 빌드를 뽑아 전달하는 일이 반복됐습니다. 자동화 이전에는 그 전달이 전부 사람 손이었습니다.
브랜치와 배포 경로
위 확인 흐름을 코드 저장소에서는 브랜치로 나눕니다. 규칙은 Gitflow에 가깝습니다. 일하는 방식과 브랜치 이름은 별개입니다. 스쿼드 확인 단계는 그대로고, 아래는 그 단계를 git에 어떻게 올렸는지입니다.
| 브랜치 | 역할 |
|---|---|
feature/* | 기능 개발 |
develop | 통합 |
release/* | 배포 후보 |
staging/* | 내부 확인용 Staging 배포 |
production/* | 스토어 직전 Production 배포 |
규칙은 있었는데, 확인용 앱은 브랜치에 자동으로 묶이지 않았습니다. 필요할 때마다 사람이 Xcode로 뽑아 Firebase나 TestFlight에 올렸습니다.
배포처
| 환경 | 역할 | 배포처 |
|---|---|---|
| Staging | PM·디자이너 공유 | Firebase App Distribution (설치 링크로 배포) |
| Production | 스토어 직전 | TestFlight (애플 베타) |
수동 배포의 비효율
가장 자주 돌던 건 Staging 배포였습니다. 코드를 고친 뒤 내부 확인이 필요할 때마다 새 빌드가 필요했고, 그때마다 제 손이 들어갔습니다.
절차는 정해져 있었습니다. 코드를 수정하고, Xcode에서 Archive를 돌려 20분쯤 기다리고, Organizer에서 .ipa(기기에 설치하는 앱 묶음 파일)를 Export하고, Firebase App Distribution에 올린 뒤 설치 링크를 공유합니다. Production도 흐름은 같고, 배포 대상만 TestFlight로 바뀌며 빌드 번호 확인과 업로드 처리 대기가 더 붙었습니다.
업로드가 끝나면 Slack으로 PM과 디자이너를 멘션해 확인을 부탁했습니다. 빌드는 올렸지만, “누가 무엇을 보면 되는지”는 여전히 사람이 적어야 했습니다.

| 환경 | 기존 배포 방식 | 수동으로 직접 하던 일 |
|---|---|---|
| Staging | Ad Hoc + Firebase App Distribution | Archive, .ipa Export, 업로드, 링크 공유 |
| Production | App Store 프로파일 + TestFlight | 빌드 번호 확인, Archive, 업로드, 처리 상태 확인 |
한 단계가 길다는 것보다, 확인이 올 때마다 처음부터 다시 밟아야 한다는 점이 더 컸습니다. Archive 20분은 그중 한 조각일 뿐이고, Export와 업로드, 링크 공유까지 매번 사람이 붙어 있어야 끝났습니다. 빌드를 걸어 두고 기다리는 20분은 다른 작업에 온전히 쓰기 애매했고, 그렇다고 손을 완전히 놓을 수도 없었습니다.
여기에 한 가지가 더 있었습니다. React Native 서브모듈, pod install, 네이티브 컴파일까지 한 번에 물고 가는 구조라서, 배포를 CI로 옮기는 순간 빌드 Job 병목이 한꺼번에 드러날 가능성이 높았습니다. 풀 문제는 두 겹이었습니다.
- 사람 손이 계속 들어가는 배포 시작을 개인 Mac에서 떼는 일
- 그다음 CI가 같은 준비를 반복하는 비용을 줄이는 일
빌드와 배포에서 이 비효율을 줄이고, 개발에 더 집중할 수 있게 GitHub Actions 자동화를 잡았습니다.
자동화한 프로세스
자동화한 프로세스는 다음과 같습니다.
- 배포 빌드 요청 (
staging/*또는production/*push) - GitHub Actions가 해당하는 워크플로를 호스티드 macOS 러너에서 실행
- 러너가 빌드를 생성해 Firebase App Distribution 또는 TestFlight에 업로드
- 업로드 완료 후 Slack으로 PM·디자이너에게 알림
인증서(.p12)는 GitHub Secrets에 두고 러너 키체인에 넣습니다. 프로파일은 Fastlane sigh가 배포마다 맞춥니다.
러너는 프로비저닝 프로파일(앱과 기기, 인증서 조합을 담은 설치 허가증. 줄여서 프로파일)을 맞춘 뒤 서명 없이 Archive하고, 코드 서명(팀이 이 앱을 배포할 권한이 있다는 도장)과 .ipa Export를 거쳐 배포처에 올린 다음 Slack으로 알립니다. 단계별 상세는 아래 워크플로 절에 둡니다.
GitHub Actions 선택 이유
결과적으로 위 프로세스는 GitHub Actions로 자동화했습니다. 가장 단순한 대안부터 검토했습니다.
| 대안 | 한계 |
|---|---|
| 체크리스트만 강화 | Archive 대기와 집중 끊김은 그대로 |
| Fastlane/셸을 제 Mac에서만 | 실행이 개인 Mac에 남고, 팀 공통 절차로 고정하기 어려움 |
| DerivedData 통째 재사용 | 깨짐 설명·운영 부담이 큼 |
검토 끝에 이미 쓰던 브랜치 규칙에 맞춰 GitHub Actions에서 배포를 시작하는 쪽이 가장 현실적이었습니다.
접근성
GitHub Actions의 큰 장점은 접근성입니다. 저장소에 워크플로 파일만 두면 설정이 끝나고, Marketplace와 템플릿으로 빠르게 붙여 볼 수 있습니다.
센디에서 주로 필요한 흐름은 Archive → Firebase 또는 TestFlight 업로드 → Slack 알림이었습니다. 이미 Fastlane lane(배포 절차를 스크립트로 묶은 단위)이 있었기 때문에, Actions 스텝에서 lane을 호출하고 트리거만 붙이면 됐습니다.
저장소 이벤트도 그대로 쓸 수 있습니다. staging/* / production/* push, 또는 수동 실행(workflow_dispatch)을 트리거로 걸었습니다. 이미 쓰던 브랜치 규칙에 배포 시작을 붙인 셈입니다.
용어를 한 줄로 정리하면 이렇습니다.
- GitHub Actions: push(또는 버튼)로 원격 Mac에서 빌드·배포를 돌리는 서비스
- 러너: 그 원격 Mac. 클라우드가 빌려 주는 장비를 호스티드 러너라고 부릅니다
- CI: 이런 원격 자동 실행 전체를 가리키는 말
- Fastlane: iOS 배포 절차를 스크립트로 돌리는 도구
러너
콴다처럼 self-hosted runner(여분 Mac을 빌드 전용으로 등록)를 둘 여유는 없었습니다. GitHub 호스티드 macOS 러너를 써서 제 Mac을 비우는 쪽을 택했습니다. 클라우드 러너 비용은 있지만, 개인 장비가 배포에 묶이는 비용을 먼저 줄이는 선택이었습니다.
다만 여기서 끝내면 빌드 Job이 새 병목이 될 가능성이 컸습니다. 더 큰 macOS 러너만 쓰면 반복 설치와 반복 컴파일 자체는 줄지 않습니다. 그래서 먼저 배포 시작을 CI로 옮기고, 그다음 반복 비용이 큰 구간만 캐시로 줄이는 두 단계로 가기로 했습니다.
GitHub Actions 워크플로 사용 예시
지금 쓰는 빌드와 배포는 대부분 워크플로로 잡혀 있습니다. 개발자가 하는 일은 적절한 브랜치에 push하거나 워크플로를 실행하는 정도입니다. 기능 확인부터 스토어 직전까지 자주 쓰는 두 워크플로를 중심으로 역할과 동작을 정리합니다.
Staging Release 워크플로
내부 확인용입니다. 기능 확인과 내부 확인 구간에서 빌드 전달이 잦아서, 이 경로를 먼저 자동화했습니다.
기능 개발은 develop에서 feature/*를 따서 진행합니다. 이 브랜치에서는
개발 → 빌드 → 수정 → 개발 → …
사이클을 반복합니다. 확인용 앱을 여러 번 나눠 줘야 해서, feature/*(또는 통합본)을 staging/*에 올리면 Staging Release 워크플로가 일련의 배포를 대신합니다.
staging/* push(또는 수동 실행)로 워크플로가 돌면 프로파일을 맞추고 archive와 서명, .ipa까지 만든 뒤 Firebase App Distribution에 올립니다. 스쿼드 단위 테스터 그룹에게 전달되고, Slack에 Started / Completed가 옵니다.
자동화 이후에는 브랜치가 배포처를 정합니다. feature/* 쪽 커밋을 staging/*으로 올리면 Firebase 빌드가 나갑니다. 배포 대상을 워크플로 입력에서 고를 필요가 없습니다.
Firebase Releases에도 브랜치 이름이 붙은 빌드가 쌓입니다. (이슈 번호는 가렸습니다.)

입력
| 항목 | 내용 |
|---|---|
| 트리거 | staging/* push (수동 실행도 가능) |
| 배포처 | Firebase App Distribution |
| 프로파일 | Ad Hoc (등록된 테스트 기기에만 설치) |
| 테스터 | 그룹 alias (스쿼드 단위 그룹) |
워크플로
- Checkout · Ruby · Xcode
- 프로파일 동기화 (
sync_signing/sigh,force: true) - 빌드 준비 (서브모듈·JS 의존성·환경 값·Pods 설치)
- 서명 없는
xcodebuild archive - 서명 ·
.ipaexport - Firebase 업로드
- Slack Started / Completed
파일은 staging-release.yml입니다. workflow_dispatch와 concurrency도 둡니다. 같은 브랜치에서 새 실행이 오면 이전 실행은 취소합니다. Archive가 겹치면 러너 비용만 늘고, 어떤 빌드를 봐야 할지도 헷갈리기 때문입니다.
Staging은 Ad Hoc이라 App Store Connect에 테스트 기기를 추가하면 프로파일을 다시 발급해야 합니다. 예전에는 사람이 콘솔에서 재발급했고, 놓치면 Archive 뒤에야 설치가 깨졌습니다. 지금은 배포가 시작되면 먼저 프로파일을 새로 받은 뒤 Archive합니다. 서명 실패는 Archive 전에 끝나게 Job을 나눴습니다.
Actions 한 실행 샘플
한 번의 Staging Release 실행 기준입니다.
- 전체 12분 17초
build9분 53초 ·sign-export1분 ·distribute1분 3초 ·notify5초


Slack Completed 샘플은 12분 13초입니다. 둘 다 한 실행이지 평균이나 로컬 20분 전/후가 아닙니다.
Production Release 워크플로
Staging에서 확인과 수정이 끝나면 스토어 직전 확인으로 넘어갑니다. 출시 후보가 release/*에 모이면 production/*에 올려 Production Release를 돌립니다.
이후에는 같은 워크플로로
빌드 → TestFlight 공유 → 피드백 → 수정 → 빌드 → …
를 반복하며 스토어 제출 직전까지 맞춥니다.

Staging과 단계는 같고, 환경 값과 배포처, 빌드 번호만 다릅니다. 파일은 production-release.yml입니다.
입력
| 항목 | 내용 |
|---|---|
| 트리거 | production/* push |
| 배포처 | TestFlight |
| 프로파일 | App Store |
| 빌드 번호 | TestFlight 마지막 번호 조회 후 +1 |
워크플로
Staging 워크플로에서 세 가지만 바뀝니다.
- 빌드 준비가 Staging 환경 값 → Production 환경 값으로 바뀝니다
- Archive 앞에 다음 빌드 번호 조회(
get_next_build_number)가 붙습니다 - 업로드 대상이 Firebase App Distribution → TestFlight로 바뀝니다
TestFlight는 같은 빌드 번호를 두 번 올리는 걸 허용하지 않습니다. 예전에는 업로드 직전 콘솔에서 마지막 번호를 확인하고 손으로 올렸습니다. 이 확인을 한 번이라도 빠뜨리면 업로드가 막힙니다. Fastlane에는 로컬 프로젝트 번호를 하나 올려 주는 increment_build_number가 있지만, CI는 매번 깨끗한 상태로 시작해 로컬 히스토리가 없습니다. 그래서 로컬 증가 대신 TestFlight에 올라간 마지막 번호를 조회해 그다음 값을 쓰는 get_next_build_number 쪽이 CI에서 더 안전했습니다.
두 워크플로는 구조가 같습니다. 갈라지는 것은 트리거와 프로파일 종류, 배포처뿐입니다.
프로파일과 서명, 인증
sigh를 고른 이유
Fastlane을 붙일 때 먼저 정해야 하는 건 인증서와 프로파일을 어떻게 다루느냐였습니다. Fastlane은 두 방식을 줍니다.
| 방식 | 요약 | 단점 |
|---|---|---|
cert · sigh | App Store Connect에서 필요할 때 받아 씀 | 인증서가 Mac·계정에 흩어질 수 있음 |
match | private git에 암호화해 공유 | 저장소·복호화 키 운영 비용 |
match는 인증서 만료를 한곳에서 갱신할 수 있어 iOS 개발자가 여럿인 팀에서 강합니다. 대신 인증서 저장소와 복호화 키를 따로 관리해야 하는 비용이 붙습니다.
센디 iOS는 제가 혼자 맡고 있어서 인증서가 여러 곳에 흩어져 만료가 제각각으로 도는 문제 자체가 없었습니다. match가 푸는 문제가 아직 우리에겐 없는 셈이라, 저장소와 키를 새로 떠안기보다 sigh로 배포마다 프로파일만 맞추는 쪽을 택했습니다. iOS 개발자가 늘면 그때 match로 옮기는 편이 맞다고 봤고, 그 경계는 인증서 갱신을 누가 언제 했는지 사람이 기억해야 하는 순간이 될 것입니다.
lane은 sync_signing입니다. Staging이면 Ad Hoc, Production이면 App Store 프로파일을 받습니다.
lane :sync_signing do
adhoc = env!("EXPORT_METHOD") == "ad-hoc"
setup_api_key
sigh(
app_identifier: env!("APP_IDENTIFIER"),
adhoc: adhoc,
force: true,
filename: env!("PROFILE_FILENAME"),
output_path: env!("PROFILE_OUTPUT_PATH")
)
endforce: true는 실무적인 선택이었습니다. Ad Hoc은 등록된 테스트 기기 구성이 바뀌면 프로파일을 다시 맞춰야 할 때가 있는데, 사람이 매번 기억해 갱신하기보다 배포 시작 시점에 동기화하는 편이 운영상 안전했습니다.
서명 없는 archive
빌드 단계의 환경 준비는 Makefile로 통일했습니다. archive는 서명 없이 먼저 만듭니다.
- name: Build Archive
run: |
xcodebuild -workspace App.xcworkspace \
-scheme App-Staging \
-configuration Debug \
-archivePath $RUNNER_TEMP/App.xcarchive \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO \
clean archive이유는 빌드와 서명을 분리해 실패 지점을 좁히고, CPU를 많이 쓰는 단계와 자격 증명을 다루는 단계를 나누기 위해서였습니다. build Job은 macos-26-xlarge, 나머지 Job은 기본 러너로 나눴습니다.
CI 인증
로그인 방식도 한 번 더 갈랐습니다. 로컬에서 Fastlane을 처음 돌리면 애플 계정 로그인과 이중 인증을 매번 요구합니다. appleid.com에서 앱 전용 암호를 발급해 넣으면 이 반복이 사라집니다. 다만 CI에서는 앱 전용 암호보다 App Store Connect API 키가 낫다고 판단했습니다. 키는 계정 비밀번호와 분리돼 있고, 권한 범위를 좁혀 발급하고 언제든 회수할 수 있어 러너에 두기에 안전했습니다. 그래서 로컬 편의는 앱 전용 암호로, CI 인증은 API 키(setup_api_key)로 갈라 두었습니다.
Firebase 업로드는 서비스 계정 키를 GitHub Secrets에 넣었습니다.


테스터는 이메일을 한 명씩 쓰지 않고 그룹 alias로 배포합니다. 스쿼드 단위 그룹을 기본값으로 씁니다.
배포 결과 알림
마지막 알림 단계는 팀 채널로 올립니다. 예전에는 업로드를 끝낸 뒤 “새 빌드 올렸어요”를 제가 직접 썼습니다. 지금은 워크플로가 Started / Completed 메시지에 소요 시간과 각 단계 결과(성공과 실패)를 붙여 보냅니다.
PM과 디자이너는 채널에서 배포가 끝났는지, 어느 단계에서 막혔는지부터 봅니다. 실패했을 때 차이가 큽니다. archive를 20분 돌린 뒤 콘솔을 뒤지던 과정이 줄고, 서명과 프로파일 문제는 archive 전에 알림으로 먼저 걸립니다.
1단계에서 바뀐 것
| 항목 | 기존 | 변경 후 |
|---|---|---|
| Staging 시작 | Xcode 수동 | staging/* push |
| Production 시작 | 번호 확인 후 수동 | production/* push |
| 프로파일 | 콘솔 재발급 | 배포 시작 시 자동 |
| 결과 공유 | 사람 전달 | Slack |
archive가 바로 빨라진 것은 아닙니다. 배포 시작과 재발급 손이 줄었습니다. 동시에 새 문제도 드러났습니다. 이제는 사람이 아니라 CI가 기다렸고, 그 시간의 대부분이 반복 설치와 반복 컴파일에 쓰였습니다.
단점과 예상치 못한 변수
배포 시작을 CI로 옮긴 뒤에도 빌드가 “빠르다”고 느껴지지는 않았습니다.
React Native 서브모듈 때문에 빌드 전에 git submodule update, JS 의존성 설치, 환경 값 생성, pod install이 함께 돌았고, 로컬에서 익숙한 준비 과정이 CI에서는 전부 대기 시간으로 잡혔습니다. Staging과 Production을 분리한 덕분에 흐름은 명확해졌지만, 스킴과 프로파일, 배포처, 빌드 번호 정책까지 환경별로 다른 부분은 워크플로에 그대로 반영해야 했습니다.
정리하면 이렇습니다.
- 서브모듈·JS 설치·환경 값·
pod install이 CI 대기로 잡힙니다 - Staging/Production 분기값은 워크플로에 그대로 남습니다
- 사람 대기 → 러너 대기로 옮겼을 뿐, 반복 준비 비용은 그대로입니다
다음 과제는 배포 시작이 아니라 빌드 단계의 반복 구간입니다.
빌드 반복 비용 단축
자동화 이후 빌드 Job은 서브모듈 동기화, JS 의존성 설치, 환경 값 생성, pod install, xcodebuild Archive로 이어졌습니다. 이 단계 중 대부분은 매 실행마다 크게 달라지지 않았습니다. Podfile.lock이 그대로인데도 pod install은 다시 돌았고, React Native 의존성이 바뀌지 않았어도 네이티브 컴파일은 반복됐습니다.
캐시는 빌드 Job에만 걸었고, 범위도 배포 전체가 아니라 가장 오래 걸리던 빌드 단계로 한정했습니다. 먼저 본 것도 빌드 로그입니다. 어디가 느린지 모른 채 캐시부터 넣으면 설명하기 어려운 최적화만 남기기 쉽기 때문입니다.
CocoaPods 캐시
먼저 CocoaPods 캐시를 넣었습니다. Pods/는 설치 결과를 재사용하게 하고, ~/Library/Caches/CocoaPods까지 같이 두면 캐시 미스가 나도 다시 내려받는 비용을 줄일 수 있습니다. 키는 Podfile.lock 해시로 두어 의존성이 바뀔 때만 새 캐시를 쓰도록 했습니다.
다만 클린 빌드 경로에서는 Pods가 함께 지워져서, 이 캐시만의 CI 단축은 단정하지 않습니다.
- name: Cache CocoaPods
uses: actions/cache@v4
with:
path: |
Pods
~/Library/Caches/CocoaPods
key: pods-${{ runner.os }}-${{ hashFiles('**/Podfile.lock') }}
restore-keys: |
pods-${{ runner.os }}-ccache
다음은 C/C++ 컴파일 캐시였습니다. React Native 쪽 node_modules 캐시를 먼저 붙이는 것도 가능했지만, 당시 병목과 무효화 기준을 함께 봤을 때 CocoaPods와 네이티브 컴파일이 더 설명 가능한 순서였습니다.
- name: Install ccache
run: |
brew install ccache
echo "$(brew --prefix ccache)/libexec" >> $GITHUB_PATH
- name: Cache ccache
uses: actions/cache@v4
with:
path: ~/Library/Caches/ccache
key: ccache-${{ runner.os }}-${{ hashFiles('**/Podfile.lock') }}
restore-keys: |
ccache-${{ runner.os }}-로컬 실측(도입 시점)은 클린 6분 5초 → 히트 3분 58초입니다. 이 숫자는 로컬 컴파일 구간만의 축이고, Archive 20분이나 CI 12분대와 전/후가 아닙니다. CI에도 같은 캐시를 넣었습니다. build가 한 실행의 대부분이라 이득도 그쪽에 모입니다. CI 평균 분은 이 글에 넣지 않았습니다. 러너나 히트 여부가 실행마다 다르기 때문입니다.
한계
- Clean Build면 캐시 이득이 거의 없습니다
- “빌드가 사라졌다”가 아니라 반복 구간 비용이 줄었습니다
- 원인 불명 재빌드가 다시 길어질 수 있습니다
2단계에서 바뀐 것
- 1단계: 배포 시작 대기
- 2단계: 같은 빌드 준비 재실행 비용 (체감 숫자 = 로컬 ccache)
자동화로 줄인 것은 사람 대기 시간이었고, 이번 최적화로 줄인 것은 반복 컴파일 대기였습니다.
이후 방향성
좋았던 점
버전과 빌드 번호, 프로파일 재발급처럼 사람이 놓치기 쉬운 구간이 줄었습니다. 예전에는 콘솔에서 프로파일을 다시 받거나 빌드 번호를 손으로 올리다가 누락하는 경우가 있었습니다. 워크플로로 옮긴 뒤에는 그 실수를 신경 쓸 일이 거의 없습니다.
호스티드 러너 덕분에 Archive를 붙잡고 있지 않아도 배포가 이어집니다. 워크플로만 돌리고, 끝나는 동안 다른 작업을 하면 됩니다. 단계별 Slack으로 실패 지점도 빨리 봅니다.
이런 이득은 “배포를 자주 돌리는 환경”에서 더 크게 느껴집니다. 센디는 iOS가 한 명이라 인원 수로 효과를 곱하지는 못하지만, 혼자여도 Mac이 묶이는 비용은 그대로 아프기 때문에 1단계에서 충분히 체감됐습니다.
앞으로 할 일
지금은 배포가 필요할 때 staging/* / production/*에 push하거나 워크플로를 직접 실행합니다. 앞으로는 node_modules와 Metro 캐시, 서브모듈 준비 비용, 캐시 히트율 관측을 더 다듬으려 합니다. 불편한 지점을 보면서 워크플로를 계속 줄여 나갈 예정입니다.
처음부터 완벽한 파이프라인보다, 눈에 띄는 병목부터 설명 가능한 순서로 타는 편이 안정적이었습니다.