홈 화면 리팩터링이 병합된 뒤 기능 테스트는 모두 통과했지만, 사용자들은 앱을 처음 열 때 더 느려졌다고 보고하기 시작했습니다. 시작 성능은 일상적인 개발 과정에서 놓치기 쉽습니다. 새 데이터베이스 마이그레이션, 동기식 설정 읽기, 분석 모듈 초기화, 대용량 이미지 로딩 등이 메인 스레드에 소요 시간을 조용히 추가할 수 있기 때문입니다. 사람이 직접 체감한 뒤 문제를 발견하기를 기다리는 대신, 고정된 클라우드 Mac에서 콜드 스타트 측정을 병합 게이트로 운영하는 편이 낫습니다.
비교 가능한 시작 시나리오부터 정의하기
“앱 열기”만으로는 완전한 테스트 정의가 되지 않습니다. 최소한 빌드 구성, Simulator 기종, 시스템 런타임, 앱의 초기 데이터, 시작 인수를 고정해야 합니다. 테스트 목표도 하나로 한정해야 합니다. 예를 들어 프로세스 생성부터 처음으로 상호작용 가능한 화면이 나타날 때까지만 측정하고, 로그인 요청이나 테스트 데이터 다운로드는 결과에 포함하지 않습니다.
별도의 Performance.xctestplan을 만들고 시작 성능 테스트만 활성화한 뒤 무작위 실행을 비활성화하는 것이 좋습니다. 시작 인수를 사용해 테스트 환경이 항상 동일한 화면으로 진입하도록 합니다.
final class LaunchPerformanceTests: XCTestCase {
override func setUp() {
continueAfterFailure = false
}
func testColdLaunch() {
let app = XCUIApplication()
app.launchArguments = ["-uiTesting", "-resetLocalState"]
let options = XCTMeasureOptions()
options.iterationCount = 8
measure(
metrics: [XCTApplicationLaunchMetric(waitUntilResponsive: true)],
options: options
) {
app.launch()
}
}
}
-resetLocalState는 앱의 테스트 진입점에서 처리하고, 다시 생성할 수 있는 로컬 상태만 정리해야 합니다. 실제로 측정해야 하는 초기화 작업을 이 인수에 따라 프로덕션 코드 경로에서 건너뛰면 안 됩니다. 그렇게 얻은 결과는 “테스트 전용 시작 속도”일 뿐입니다.
클라우드 Mac과 Simulator 상태 고정하기
성능 게이트에는 알 수 없는 작업과 CPU 및 디스크를 두고 경쟁하는 공유 환경이 아니라 전용 물리 머신이 필요합니다. 실행할 때마다 먼저 현재 Xcode 경로, 사용 가능한 Simulator, 남은 디스크 공간을 확인합니다.
set -euo pipefail
xcode-select -p
xcodebuild -version
xcrun simctl list devices available
df -h "$HOME"
테스트 계획에서 설치된 Simulator 하나를 지정합니다. 스크립트가 “사용 가능한 첫 번째 기기”를 자동으로 선택하게 해서는 안 됩니다. 이미지가 바뀌면 과거 데이터와 비교할 수 없게 되기 때문입니다. 게이트가 실행되는 동안에는 병렬 아카이브, 의존성 업데이트, 대규모 인덱싱 작업도 피해야 합니다.
성능 데이터는 코드 데이터이기 전에 환경 데이터입니다. 실행 노드, 빌드 구성, Simulator 상태를 설명할 수 없는 수치는 병합을 직접 차단하는 기준으로 사용하기에 적합하지 않습니다.
최초 기준선을 만들 때는 동일한 커밋에서 테스트를 반복 실행해야 합니다. 결과의 편차가 확연히 크다면 임계값부터 완화하지 말고 백그라운드 작업, 디스크 부하, 테스트 데이터 초기화 로직을 먼저 점검합니다.
xcodebuild로 단일 게이트 실행하기
명령줄 작업에서는 대상 테스트만 실행하고 결과 번들을 파이프라인 산출물로 보관합니다. 기기 이름은 실제 테스트 계획에 고정한 모델로 바꿔야 합니다.
set -o pipefail
mkdir -p Artifacts
xcodebuild test \
-workspace App.xcworkspace \
-scheme App \
-testPlan Performance \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-only-testing:AppUITests/LaunchPerformanceTests/testColdLaunch \
-resultBundlePath Artifacts/Launch.xcresult \
| tee Artifacts/launch-test.log
set -o pipefail은 매우 중요합니다. 이 설정이 없으면 xcodebuild가 실패해도 파이프라인 끝의 tee 때문에 작업이 성공한 것으로 처리될 수 있습니다. Launch.xcresult와 텍스트 로그를 모두 보관해야 합니다. 전자는 각 측정 결과와 테스트 첨부 파일을 확인하는 데 사용하고, 후자는 컴파일 또는 시작 단계의 오류를 빠르게 찾는 데 유용합니다.
| 점검 항목 | 고정 방법 | 변경 후 처리 |
|---|---|---|
| Xcode | xcodebuild -version 기록 |
후보 기준선부터 다시 생성 |
| Simulator | 기종과 런타임 고정 | 기존 기준선과 직접 비교하지 않음 |
| 빌드 구성 | 동일한 테스트 계획 사용 | 임시 인수 재정의 거부 |
| 테스트 데이터 | 시작 인수로 결정적 초기화 수행 | 초기화가 완전한지 확인 |
| 반복 횟수 | 게이트에서 항상 8회 사용 | 단일 결과만으로 판단하지 않음 |
단일 수치를 좇지 말고 기준선 관리하기
Xcode 테스트 보고서에서 지정한 테스트의 성능 기준선을 만들고, 생성된 공유 기준선 파일을 버전 관리에 포함합니다. 기준선 변경은 의존성 잠금 파일처럼 검토해야 합니다. 커밋 설명에는 변경 원인, 검증에 사용한 커밋, 예상 영향을 명확히 기록해야 하며, 단순히 “성능 데이터 업데이트”라고만 적어서는 안 됩니다.
알림 임계값과 차단 임계값을 구분해야 합니다. 작은 변동은 추세 관찰 대상으로 남겨 두고, 반복 실행 후에도 허용 범위를 계속 벗어나는 변화는 실패로 처리할 수 있습니다. 실제 판단 기준은 한 번의 실행에서 나온 가장 빠른 기록이 아니라, 동일한 환경에서 반복 측정한 결과가 검토된 기준선에서 안정적으로 벗어나는지 여부입니다.
다음과 같은 경우에는 기준선을 바로 업데이트하면 안 됩니다.
- 테스트 노드에서 다른 고부하 작업이 동시에 실행된 경우
- Simulator 기종이나 런타임이 변경된 경우
- 의존성을 처음 다운로드하는 중이거나 인덱싱이 완료되지 않은 경우
- 테스트를 통과시키기 위해 초기화 단계를 건너뛴 경우
- 한 번의 실행에서만 이상이 발생하고 나머지 결과는 정상인 경우
실패 현장을 보존하고 원인이 된 경로 찾기
게이트가 실패하면 동일한 클라우드 Mac과 동일한 커밋에서 한 번 다시 실행합니다. 결과가 재현되면 시작 경로를 프로세스 진입점, 의존성 주입, 데이터베이스 열기, 첫 화면 모델 구성, 리소스 디코딩, 첫 프레임 렌더링 단계로 나눠 점검합니다. 각 경계에 일관된 os_signpost를 추가하면 이후 분석에서 커밋 규모만 보고 추측하는 대신 어느 구간에 시간이 소요됐는지 확인할 수 있습니다.
조사는 가장 최근 변경 사항부터 시작해야 하지만, 비즈니스 코드만 살펴봐서는 안 됩니다. 빌드 구성 변경, 디버그 진단 옵션, 리소스 용량 증가, 테스트 픽스처도 시작 경로를 바꿀 수 있습니다. 수정한 뒤에는 실패한 xcresult와 통과한 xcresult를 모두 보관하고, 병합 요청에 비교 대상 커밋을 기록합니다.
신뢰할 수 있는 게이트의 가치는 시작 시간에 절대적인 평가를 붙이는 데 있지 않고, 동일한 시나리오를 지속적으로 비교할 수 있게 만드는 데 있습니다. 환경을 고정하고, 기준선을 버전으로 관리하고, 증거를 보관하며, 기준선 업데이트까지 검토 대상에 포함해야 시작 성능이 주관적인 체감에서 추적 가능한 엔지니어링 제약 조건으로 바뀝니다.
자주 묻는 질문
시작 성능 테스트는 몇 번 실행해야 하나요?
동일한 커밋에서 최소 5회, 병합 게이트에서는 8회 이상 실행하는 것이 좋습니다. Simulator 기종과 런타임, 빌드 설정, 백그라운드 작업은 동일하게 유지합니다.
게이트가 실패하면 즉시 임계값을 높여도 되나요?
그렇게 하지 않습니다. 같은 노드에서 다시 실행하고 Simulator 상태와 실행 경로를 확인한 뒤, 의도한 제품 변경으로 확인된 경우에만 새 기준선을 검토합니다.
프로젝트에 따라 켜고 끄는 클라우드 Mac으로 워크플로 재현하기
세 가지 Apple Silicon 구성 중 적합한 리소스를 선택하고 일·주·월·분기 단위로 대여하세요. 가상 머신이 아닌 전용 물리 장비이며, 실제 사용 가능 상태는 콘솔에서 실시간으로 확인할 수 있습니다.