엔지니어링 가이드

클라우드 Mac에서 Swift 컴파일 병목 진단하기

클라우드 Mac에서 Swift 컴파일 병목 진단하기

클라우드 Mac에서 Swift 컴파일 병목 진단하기

Swift 모듈의 컴파일 시간이 수십 초에서 점차 수분대로 늘어났다면 곧바로 코드를 다시 작성하거나 병렬 처리 수준부터 높여서는 안 됩니다. 원격 환경에서는 의존성 해석, 빌드 스크립트, 링크, 타입 검사에 걸리는 시간이 모두 Xcode의 전체 빌드 시간에 포함됩니다. 효과적으로 원인을 파악하려면 클라우드 Mac의 툴체인과 입력을 고정하고 단계별 근거를 확보한 다음, 문제 범위를 특정 소스 파일과 표현식까지 좁혀야 합니다.

재현 가능한 측정 기준선부터 만들기

다른 빌드 작업이 실행되지 않는 시간대를 선택하고 코드 커밋, Scheme, Configuration, SDK, 대상 아키텍처를 고정합니다. xcodebuild -version, 현재 커밋, 실제 실행 명령을 기록합니다. 클린 빌드 한 번과 증분 빌드 한 번을 직접 비교해서는 안 됩니다. 두 빌드는 서로 다른 질문에 대한 결과이기 때문입니다.

mkdir -p "$HOME/build-audit"
xcodebuild -version > "$HOME/build-audit/toolchain.txt"
git rev-parse HEAD > "$HOME/build-audit/commit.txt"

set -o pipefail
/usr/bin/time -l xcodebuild \
  -workspace MyApp.xcworkspace \
  -scheme MyApp \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -showBuildTimingSummary \
  build \
  2>&1 | tee "$HOME/build-audit/baseline.log"

먼저 일반적인 증분 빌드를 연속으로 세 번 실행해 소요 시간의 변동 폭이 안정적인지 확인합니다. 클린 빌드를 측정해야 한다면 명시적으로 clean을 실행하거나 별도의 DerivedData 경로를 사용하고, 최적화 전후에 완전히 동일한 정리 방식을 적용해야 합니다.

한 번의 최단 기록만으로 결론을 내려서는 안 됩니다. 동일한 조건에서 여러 차례 실행한 결과의 중앙값을 비교하고, 가장 오래 걸린 실행의 로그도 보관해 간헐적인 스크립트 실행, 네트워크 요청 또는 리소스 경합을 점검해야 합니다.

단계별 요약으로 조사 방향 정하기

Build Timing Summary에는 컴파일, 링크, 리소스 처리, 스크립트 등의 단계가 표시됩니다. 마지막 줄의 전체 소요 시간만 보지 말고, 비중이 가장 크면서 반복적으로 나타나는 항목부터 찾습니다.

현상 우선 점검 항목 흔한 오판
SwiftCompile이 오랫동안 가장 큰 비중을 차지함 타입 검사, 개별 파일 크기, 배치 컴파일 동작 링크가 느리다고 오해함
Run Script가 매번 실행됨 입력·출력 파일, 스크립트 내부의 검색 범위 머신의 병렬 처리 수준만 높임
의존성 해석 시간이 불안정함 잠금 파일, 저장소 접근, 해석 작업의 반복 여부 Swift 컴파일 문제로 간주함
Link 단계가 두드러짐 링크 입력, 디버그 심볼, 중복 라이브러리 비즈니스 로직 표현식을 다시 작성함

스크립트에 입력과 출력이 선언되어 있는지도 확인해야 합니다. 의존성 경계가 없는 스크립트는 증분 빌드 때마다 실행되어 소스 코드 최적화 효과를 가릴 수 있습니다. 스크립트에 다운로드 작업이 포함되어 있다면 네트워크 대기 시간과 로컬 연산 시간을 분리해 측정합니다.

느린 함수와 표현식 찾기

병목이 Swift 컴파일에 있다는 사실을 확인한 뒤 프런트엔드 진단 매개변수를 임시로 추가합니다. 팀의 일상적인 설정에 영향을 주지 않도록 별도의 진단용 Configuration에서 OTHER_SWIFT_FLAGS로 설정할 수 있습니다.

-Xfrontend -debug-time-function-bodies
-Xfrontend -debug-time-expression-type-checking

동일한 빌드 명령을 다시 실행하고 표준 오류도 함께 저장합니다. 로그에는 일반적으로 소요 시간, 파일 위치, 함수 또는 표현식이 표시됩니다. Xcode 툴체인에 따라 출력 형식과 임계값이 달라질 수 있으므로, 분석 스크립트에서 열 개수가 항상 고정되어 있다고 가정해서는 안 됩니다.

무엇부터 처리해야 하는가

먼저 소요 시간순으로 정렬한 뒤 파일 단위로 집계합니다. 수백 번 반복해서 컴파일되는 중간 수준의 핫스폿이 매우 느린 단일 함수보다 우선순위가 높을 수 있습니다. 비용이 많이 드는 대표적인 코드로는 지나치게 긴 제네릭 체인, 중첩 클로저, 분기가 많은 단일 표현식, 컴파일러가 여러 중간 타입을 동시에 추론해야 하는 컬렉션 변환 등이 있습니다.

수정할 때는 표현식 분리, 중간 값의 명시적 타입 지정, 대형 함수를 경계가 분명한 작은 함수로 분할하는 작업처럼 한 번에 한 종류의 문제만 처리합니다. 컴파일 설정과 소스 코드를 동시에 변경하면 어느 쪽에서 개선 효과가 발생했는지 판단할 수 없습니다.

최소한의 변경으로 원인 검증하기

어떤 코드가 필터링, 매핑, 딕셔너리 생성, 옵셔널 값 처리를 하나의 표현식으로 연결하고 있다면 먼저 중간 결과에 이름과 타입을 지정해 볼 수 있습니다. 목표는 소스 코드를 더 짧게 만드는 것이 아니라 타입 검사기가 한 번에 풀어야 하는 제약 조건을 줄이는 것입니다.

let validItems: [Item] = items.filter { $0.isValid }
let identifiers: [String] = validItems.map(\.identifier)
let result: [String: Item] = Dictionary(
    uniqueKeysWithValues: zip(identifiers, validItems)
)

수정을 마치면 기준 커밋에서 해당 변경만 추가한 브랜치로 다시 측정합니다. 최소한 다음 세 가지를 확인해야 합니다. 핫스폿 로그에서 해당 표현식의 시간이 줄었는지, SwiftCompile 단계가 단축되었는지, 여러 차례 실행했을 때 전체 빌드 시간이 안정적으로 개선되었는지입니다. 전체 시간만 달라지고 핫스폿에는 변화가 없다면 소스 코드 수정의 효과로 단정하지 말고 캐시나 백그라운드 작업을 계속 점검해야 합니다.

진단을 유지 가능한 검증 절차로 만들기

진단 매개변수를 모든 빌드에 장기간 적용하는 것은 적절하지 않습니다. 별도의 성능 점검 작업을 만들고 필요할 때 실행하면서 툴체인, 커밋, 명령, 요약을 보관하는 편이 더 안정적입니다. 로그에는 로컬 경로, 저장소 구조, 환경 변수의 확장 결과가 포함될 수 있으므로 업로드 전에 민감한 정보를 제거해야 합니다.

조사할 때마다 다음 내용을 저장하는 것이 좋습니다.

  1. Xcode 및 Swift 버전.
  2. Git 커밋과 빌드 구성.
  3. 클린 빌드 또는 증분 빌드 여부를 나타내는 명확한 표기.
  4. 세 번 이상 실행한 원본 소요 시간.
  5. 단계별 요약과 주요 소스 코드 핫스폿.
  6. 변경 전후의 유일한 차이와 롤백 방법.

클라우드 Mac에서 결과 변동이 크다면 병렬 빌드, 인덱싱 작업 또는 남아 있는 스크립트가 실행 중인지 먼저 확인한 뒤 다시 측정합니다. MiniRent는 전용 물리 노드를 제공하지만, 동일한 장비에서 사용자가 실행한 작업끼리는 여전히 CPU, 메모리, 디스크를 두고 경합할 수 있습니다. 신뢰할 수 있는 결론은 한 번 더 빨라 보이는 빌드가 아니라 통제된 입력, 재현 가능한 명령, 빠짐없이 보존한 근거에서 나옵니다.

자주 묻는 질문

Xcode 전체 빌드 시간만 비교하면 왜 정확하지 않나요?

전체 시간에는 의존성 해석, 캐시 상태, 스크립트, 컴파일과 링크가 모두 포함됩니다. 커밋과 Xcode 버전을 고정한 뒤 각 단계를 따로 비교해야 합니다.

Swift 시간 진단 옵션을 프로젝트에 계속 두어도 되나요?

권장하지 않습니다. 로그가 크게 늘고 도구 체인에 따라 동작이 달라질 수 있습니다. 조사 실행에서만 켜고 결과를 보관한 뒤 제거하는 편이 안전합니다.

전용 클라우드 Mac

전용 물리 노드에서 빌드 작업 실행

일·주·월·분기 단위로 MiniRents M4 및 MiniRents M4 Pro를 선택하고, 팀과 코드 저장소 위치에 맞는 노드를 선택하세요. 장비는 전용 물리 머신이며 가상 머신이 아닙니다.

모델 선택 및 주문