
iOS 빌드가 터졌어요 (Xcode의 저주와 CocoaPods 디버깅)
어제는 됐는데 오늘은 안 되는 iOS 빌드. CocoaPods 의존성 지옥, M1/M2 아키텍처(arm64) 충돌, 서명(Signing) 문제, 그리고 CI/CD에서의 Fastlane 설정까지 완벽하게 파헤칩니다.

어제는 됐는데 오늘은 안 되는 iOS 빌드. CocoaPods 의존성 지옥, M1/M2 아키텍처(arm64) 충돌, 서명(Signing) 문제, 그리고 CI/CD에서의 Fastlane 설정까지 완벽하게 파헤칩니다.
로그인 화면을 만들었는데 키보드가 올라오니 노란 줄무늬 에러가 뜹니다. resizeToAvoidBottomInset부터 스크롤 뷰, 그리고 채팅 앱을 위한 reverse 팁까지, 키보드 대응의 모든 것을 정리해봤습니다.

안드로이드는 오는데 iOS는 조용합니다. 혹은 앱이 켜져 있을 때만 옵니다. Background/Terminated 상태 처리, APNs 인증서, 그리고 Notification Channel 설정까지 완벽하게 해결합니다.

안드로이드는 Xcode보다 낫다고요? Gradle 지옥에 빠져보면 그 말이 쏙 들어갈 겁니다. minSdkVersion 충돌, Multidex 에러, Namespace 변경(Gradle 8.0), JDK 버전 문제, 그리고 의존성 트리 분석까지 완벽하게 해결해 봅니다.

Debug에선 잘 되는데 Release에서만 죽나요? 범인은 '난독화'입니다. R8의 원리, Mapping 파일 분석, 그리고 Reflection을 사용하는 라이브러리를 지켜내는 방법(@Keep)을 정리해봤습니다.

Flutter 개발자가 가장 두려워하는 순간입니다. 코드는 한 줄도 안 고쳤습니다. 그냥 자고 일어났을 뿐인데, 갑자기 빌드가 빨간 에러를 토해냅니다.
ld: symbol(s) not found for architecture arm64
Sandbox: rsync.samba(...) deny(1) file-write-create
Command PhaseScriptExecution failed with a nonzero exit code
로그는 외계어 같습니다. 맥북을 던지고 싶겠지만, 잠깐 참으세요. 이것은 여러분의 잘못이 아닙니다. Xcode와 CocoaPods의 복잡한 의존성 관계가 꼬였을 뿐입니다.
Flutter의 iOS 빌드는 단순히 "컴파일" 한 번으로 끝나지 않습니다. 3단계의 복잡한 파이프라인을 거칩니다.
App.framework)로 만듭니다.pubspec.yaml에 정의된 플러그인들이 사용하는 네이티브 iOS 라이브러리(Map, WebView, Firebase 등)를 다운로드하고, 의존성을 연결합니다.Runner.app을 만듭니다.대부분의 문제는 2번과 3번 사이에서 발생합니다. CocoaPods가 다운로드한 라이브러리 버전과 Xcode가 기대하는 설정이 다르거나, 이전 빌드의 찌꺼기(Cache/Artifacts)가 남아있어서 충돌이 나는 것입니다.
가장 무식하지만, 80%의 문제를 해결하는 "성스러운 의식"입니다.
어설프게 flutter clean만 하지 말고, iOS 의존성까지 뿌리째 뽑아야 합니다.
# 1. Flutter 프로젝트 루트에서 시작
flutter clean
# 2. iOS 폴더로 이동
cd ios
# 3. CocoaPods 캐시 삭제 (가장 중요)
rm -rf Pods
rm Podfile.lock
# 4. 의존성 재설치 (Repo 업데이트 포함)
# M1/M2 맥이라면 arch -x86_64를 붙여야 할 수도 있음
pod install --repo-update
# 5. 다시 빌드
cd ..
flutter pub get
flutter run
이걸로 해결되면 다행입니다. 안 된다면 이제 진짜 디버깅을 시작해야 합니다.
애플 실리콘 맥을 쓰는데 Excluded Architectures 또는 symbol not found for architecture arm64 에러가 뜬다면?
범인은 "오래된 라이브러리"입니다.
어떤 라이브러리가 인텔(x86_64)용 바이너리만 갖고 있고, arm64(애플 실리콘)용 바이너리가 없어서 시뮬레이터 빌드가 실패하는 것입니다.
강제로 시뮬레이터 빌드에서 arm64를 제외시켜서, 로제타(Rosetta)로 돌리게 만들어야 합니다.
ios/Podfile의 post_install 블록에 아래 코드를 추가하세요.
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
# 추가된 부분
target.build_configurations.each do |config|
# 시뮬레이터(iphonesimulator) 빌드일 때만 arm64 제외
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"
end
end
end
단, 이 방법은 임시방편입니다. 장기적으로는 해당 라이브러리 개발자에게 "arm64 지원해주세요"라고 이슈를 남기거나, 라이브러리를 교체해야 합니다.
Code Signing Error, Provisioning Profile doesn't match, Entitlements mismatch.
이 에러들은 "애플이 이 앱을 누가 만들었는지 인증할 수 없다"는 뜻입니다.
터미널에서는 해결이 불가능합니다. 무조건 Xcode를 열어야 합니다.
ios/Runner.xcworkspace 파일을 더블클릭해서 엽니다. (.xcodeproj 아님!)Runner (파란 아이콘) 클릭.Runner 선택 -> Signing & Capabilities 탭 클릭.pod install을 쳤는데 ffi, ethon, gem 관련 루비 에러가 쏟아진다면?
MacOS에는 기본적으로 시스템 Ruby가 깔려있는데, 이것과 CocoaPods가 사용하는 Ruby 버전이 꼬인 겁니다.
시스템 Ruby(system)를 쓰지 말고, rbenv로 별도의 버전을 설치해서 쓰세요.
# 1. rbenv 설치
brew install rbenv ruby-build
# 2. 호환성 좋은 Ruby 버전 설치 (예 - 2.7.6 또는 3.2.2)
rbenv install 3.2.2
rbenv global 3.2.2
# 3. CocoaPods 재설치
gem install cocoapods
# 4. 확인
which pod
# 결과가 /Users/내이름/.rbenv/shims/pod 여야 함.
# /usr/bin/pod 라면 시스템 루비를 쓰고 있는 것임.
2.1.3)이 적힌 영수증.CocoaPods를 쓰면 반드시 .xcworkspace로 열어야 합니다.
Workspace는 Runner 프로젝트와 Pods 프로젝트(라이브러리들)를 하나로 묶어주는 거대한 폴더입니다.
Xcode가 빌드하는 순서입니다. Flutter는 여기에 Run Script를 끼워넣어 Dart 코드를 컴파일하고 에셋을 복사합니다.
애플이 앱을 기기에 맞춰 최적화하기 위해 사용하는 중간 코드입니다. 하지만 Xcode 14부터 Deprecated(사용 중단) 되었습니다. 빌드 설정에서 Enable Bitcode를 No로 설정해야 최신 라이브러리들과 충돌이 안 납니다.
flutter clean + rm -rf Pods + pod install은 만병통치약이다.Excluded Architectures = arm64 설정이 필요한지 확인하라..xcodeproj로 열지 말고 .xcworkspace로 열어라.