- Published on
Flutter iOS 빌드 실패 - Pods·Xcode 15 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
Flutter로 iOS 빌드를 하다 보면 “어제까지 되던 빌드가 오늘 갑자기 실패”하는 순간이 자주 옵니다. 특히 Xcode 15로 올라간 뒤에는 CocoaPods, Ruby, iOS Deployment Target, 시뮬레이터 아키텍처, 그리고 플러그인들이 생성하는 설정 파일들이 서로 얽히면서 오류가 연쇄적으로 터집니다.
이 글은 Flutter iOS 빌드 실패를 Pods 관점에서 빠르게 수습하고, Xcode 15에서 재발을 줄이는 체크리스트를 제공합니다. 단순히 pod install만 반복하기보다, 실패 원인을 분류하고 “어떤 명령을 어떤 순서로” 실행해야 하는지에 초점을 맞춥니다.
참고로, 빌드 문제를 다룰 때는 캐시/의존성/환경이 꼬이는 패턴이 비슷합니다. Docker 빌드 캐시가 무효화되는 원인을 정리한 글도 함께 보면 문제 분해에 도움이 됩니다: Docker 빌드 캐시가 무효화되는 원인 7가지
증상 패턴부터 분류하기
Xcode 15 + Flutter에서 자주 등장하는 실패 메시지는 대략 아래 범주로 나뉩니다.
1) CocoaPods/Pod 설치 단계에서 실패
CocoaPods could not find compatible versions for pod ...Specs satisfying the ... dependency were found, but they required a higher minimum deployment targetCDN: trunk URL couldn't be downloaded또는 네트워크/캐시 관련
2) Xcode 컴파일/링크 단계에서 실패
ld: library not found for -lPods-RunnerFramework not found ...Undefined symbols for architecture arm64Sandbox: rsync ... deny(권한/샌드박스)
3) 설정 파일/xcconfig 누락
Unable to open base configuration reference file ... Pods-Runner.debug.xcconfigGenerated.xcconfig must exist(Flutter iOS 설정 생성 실패)
이제부터는 “가장 재현성이 높은 해결 순서”로 정리합니다.
0단계: 환경 버전 확인(의외로 가장 중요)
Xcode 15는 iOS SDK, Swift, clang 동작이 바뀌며 플러그인/Pod의 최소 요구사항이 올라가는 경우가 많습니다. 먼저 도구 버전을 고정/확인합니다.
xcodebuild -version
flutter --version
ruby -v
pod --version
- CocoaPods가 너무 낮으면 Xcode 15 프로젝트를 제대로 처리하지 못할 수 있습니다.
- Ruby가 시스템 Ruby인 경우(특히 macOS 업데이트 후) gem 충돌이 잦습니다.
팀/CI에서 변동을 줄이려면 Bundler로 CocoaPods 버전을 고정하는 편이 안전합니다.
# ios/Gemfile
source 'https://rubygems.org'
gem 'cocoapods', '1.14.3'
cd ios
bundle install
bundle exec pod --version
1단계: Flutter 쪽 생성물부터 정상화
Generated.xcconfig 또는 Flutter tool이 생성하는 파일이 깨지면, Pods를 아무리 재설치해도 Xcode가 읽을 설정이 없습니다. 아래 순서로 Flutter 산출물을 먼저 복구합니다.
flutter clean
flutter pub get
그 다음 iOS 폴더에서 Flutter가 필요한 설정을 만들도록 한 번 iOS 빌드를 트리거합니다.
flutter build ios --no-codesign
여기서 실패한다면, CocoaPods 이전에 Flutter 자체 설정/플러그인 등록 문제가 있을 수 있습니다.
2단계: Pods를 “완전히” 초기화하고 재설치
대부분의 Pod 관련 빌드 실패는 부분 캐시가 남아서 발생합니다. 아래는 가장 흔히 효과가 있는 초기화 루틴입니다.
cd ios
rm -rf Pods
rm -rf Podfile.lock
rm -rf .symlinks
rm -rf Flutter/Flutter.podspec
# Xcode 워크스페이스/프로젝트 캐시도 함께 정리
rm -rf Runner.xcworkspace
# CocoaPods 캐시(필요할 때만)
# pod cache clean --all
bundle exec pod repo update
bundle exec pod install
Bundler를 쓰지 않는다면 bundle exec만 빼고 실행해도 됩니다. 다만 팀/CI에서는 Bundler 고정이 장기적으로 안정적입니다.
자주 놓치는 포인트: pod install은 ios 폴더에서
Flutter 루트에서 실행하면 경로가 꼬이거나, 다른 Ruby 환경을 타는 경우가 있습니다.
3단계: iOS Deployment Target 상향(가장 흔한 호환성 이슈)
Xcode 15로 올라오면서 일부 Pod가 최소 iOS 버전을 올리거나, Flutter 플러그인이 최신 SDK를 요구하는 경우가 많습니다.
오류 예시는 보통 이런 형태입니다.
required a higher minimum deployment target
해결은 ios/Podfile의 플랫폼 버전을 올리고 재설치하는 것입니다.
# ios/Podfile
platform :ios, '12.0'
프로젝트 상황에 따라 13.0 이상이 필요할 수도 있습니다. 변경 후에는 반드시 Pods를 다시 설치합니다.
cd ios
bundle exec pod install
또한 Xcode에서 Runner 타겟의 Deployment Target이 Podfile과 불일치하면 경고/오류가 꼬일 수 있으니, Xcode의 Runner 설정도 확인하세요.
4단계: Xcode 15에서 자주 터지는 아키텍처/링커 이슈
4-1) 시뮬레이터 arm64 관련 Undefined symbols/빌드 실패
Apple Silicon 환경에서 시뮬레이터가 arm64로 돌면서, 일부 바이너리 Pod가 시뮬레이터 arm64를 지원하지 않아 실패하는 경우가 있습니다.
임시 해결로는 시뮬레이터 빌드에서 arm64를 제외하는 방법이 있습니다.
# ios/Podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
end
end
end
다만 이 방법은 “근본 해결”이 아니라 회피책입니다. 가능하면 해당 Pod/플러그인을 업데이트해서 시뮬레이터 arm64를 지원하도록 맞추는 것이 좋습니다.
4-2) ld: library not found for -lPods-Runner
이 오류는 대개 워크스페이스를 열지 않고 Runner.xcodeproj를 열었거나, Pods가 깨진 상태에서 Xcode 인덱스/빌드 캐시가 남아 있을 때 발생합니다.
체크리스트:
- Xcode에서
Runner.xcworkspace를 열었는지 확인 - 위의 2단계 초기화로 Pods 재설치
- Xcode
Product메뉴에서Clean Build Folder실행(단축키는 환경에 따라 다름)
5단계: Pods-Runner.xcconfig/Base Configuration 누락
오류 예:
Unable to open base configuration reference file ... Pods-Runner.debug.xcconfig
이 경우는 보통 다음 중 하나입니다.
- Pods 폴더가 삭제되었는데 Xcode가 예전 참조를 잡고 있음
pod install이 실패했는데도 워크스페이스를 열어 빌드함.xcconfig파일 경로가 깨짐
해결 순서:
- Xcode 종료
- 2단계의 Pods 초기화 및 재설치
Runner.xcworkspace로 다시 열기
추가로, CI에서 간헐적으로 같은 문제가 난다면 “동시성/캐시” 문제일 가능성도 큽니다. 배포가 겹치거나 캐시가 경쟁 상태가 되면 산출물이 꼬입니다. 관련해서는 GitHub Actions 동시성 꼬임으로 배포 겹침 막기도 참고할 만합니다.
6단계: 네트워크/CDN 문제로 Pod 다운로드 실패
회사 네트워크, 프록시, 간헐 DNS 문제로 pod install이 실패하는 경우도 많습니다. 특히 CDN: trunk 관련 다운로드 실패는 환경 이슈일 때가 잦습니다.
대응 방법:
pod repo update를 먼저 수행- 필요 시 CocoaPods 캐시 정리 후 재시도
- CI라면 네트워크 재시도 로직을 넣거나, 사내 미러를 고려
간헐 DNS 실패처럼 “겉으로는 정상인데 특정 타이밍에만 깨지는” 유형은 인프라에서도 흔합니다. 원인 접근 방식은 비슷하니, 문제 분해 관점에서 EKS에서 CoreDNS 정상인데 DNS가 간헐 실패할 때도 도움이 됩니다.
7단계: Xcode 15에서 User Script Sandboxing 이슈
Xcode 15부터 일부 프로젝트에서 스크립트 실행이 샌드박싱 정책에 걸리며 rsync 또는 스크립트 단계가 실패하는 사례가 있습니다.
증상은 보통 Sandbox: ... deny 형태로 나타납니다. 이 경우는 프로젝트/플러그인에 따라 해법이 달라서, 우선은 다음을 확인합니다.
- 문제가 발생한 Build Phase 스크립트가 무엇인지
- 스크립트가 접근하는 경로가 빌드 허용 범위인지
- 플러그인 최신 버전에서 수정되었는지
가능하다면 플러그인을 업데이트하고, 스크립트가 임의 경로에 쓰기/읽기를 하지 않도록 조정하는 것이 정석입니다.
재현 가능한 “원샷” 복구 스크립트
로컬에서 자주 쓰는 복구 루틴을 스크립트로 만들어두면, 팀원 온보딩이나 급한 장애 대응에 도움이 됩니다.
#!/usr/bin/env bash
set -euo pipefail
flutter clean
flutter pub get
pushd ios >/dev/null
rm -rf Pods Podfile.lock .symlinks Runner.xcworkspace
# Bundler를 쓴다면
bundle install
bundle exec pod repo update
bundle exec pod install
popd >/dev/null
flutter build ios --no-codesign
CI에서는 여기에 xcodebuild -showBuildSettings로 환경을 덤프하거나, 실패 시 pod env 출력까지 남기면 원인 추적이 쉬워집니다.
문제를 줄이는 운영 팁(팀/CI 관점)
1) CocoaPods 버전 고정
- 로컬은 각자 최신, CI는 다른 버전이면
Podfile.lock이 흔들립니다. ios/Gemfile+bundle exec pod install로 고정하세요.
2) Xcode 버전 고정
- Xcode 15.x 마이너 업데이트에서도 빌드 결과가 달라질 수 있습니다.
- CI 머신에서는 Xcode 버전을 명시하고, 로컬도 가능한 맞추는 편이 좋습니다.
3) 플러그인 업데이트 정책
- iOS 네이티브 의존성이 있는 플러그인은 Xcode 업데이트 시점에 같이 업데이트하는 편이 안전합니다.
- 특히 Firebase 계열, 권한/푸시, 지도 SDK 등은 iOS 최소 버전 요구사항이 자주 바뀝니다.
마무리: “Pods 초기화”는 마지막이 아니라 중간 단계
Flutter iOS 빌드 실패를 Pods 문제로만 보면 rm -rf Pods를 무한 반복하게 됩니다. 하지만 Xcode 15에서는 다음 순서가 핵심입니다.
- Flutter 생성물 정상화(
flutter clean,pub get,build ios) - Pods 완전 초기화 후 재설치(
Podfile.lock포함) - Deployment Target/아키텍처/워크스페이스 열기 같은 구조적 설정 점검
- 네트워크/샌드박스/CI 동시성 같은 “환경 요인” 분리
위 순서대로 접근하면, 대부분의 Xcode 15 + CocoaPods 계열 빌드 실패는 재현 가능하게 정리되고, 팀 단위로도 안정화할 수 있습니다.