Published on

Flutter iOS 빌드 실패? Podfile 오류 해결법

Authors

Flutter로 iOS 빌드를 하다 보면 pod install 단계에서 멈추거나, Xcode는 열리는데 아카이브가 실패하는 등 “Podfile 오류”로 뭉뚱그려지는 문제가 자주 발생합니다. 이 글은 흔한 에러 메시지를 기준으로 원인을 좁히고, 안전한 초기화 순서Podfile 수정 포인트를 체크리스트처럼 따라 할 수 있게 정리했습니다.

빌드/캐시 문제는 iOS만의 이야기가 아닙니다. CI에서 캐시가 꼬였을 때의 점검 방식은 유사하니, 필요하면 GitHub Actions 캐시가 안 먹을 때 디버깅 체크리스트도 함께 참고하면 좋습니다.

먼저 확인: 에러가 Podfile 문제인지 구분하기

다음 중 하나라도 보이면 CocoaPods 또는 Podfile 계열 이슈일 가능성이 큽니다.

  • CocoaPods could not find compatible versions for pod ...
  • Specs satisfying the ... dependency were found, but they required a higher minimum deployment target
  • The sandbox is not in sync with the Podfile.lock
  • pod install 도중 ffi/xcodeproj/activesupport 같은 Ruby gem 에러
  • Apple Silicon에서 arm64 관련 경고/에러

반대로 아래라면 Podfile보다 Xcode 설정/서명/빌드 설정 문제일 확률이 높습니다.

  • No signing certificate / Provisioning profile 관련
  • Runner 타깃의 Build Settings에서만 해결되는 컴파일 에러

이 글은 Podfile과 CocoaPods 레이어에 집중합니다.

1) 가장 먼저 해볼 “정석 초기화” 순서

Podfile 오류는 실제로는 캐시/락파일/Pods 디렉터리 불일치인 경우가 많습니다. 아래 순서대로 정리하면, 원인을 모르는 상태에서도 많은 문제가 해결됩니다.

프로젝트 루트에서

flutter clean
rm -rf build
rm -rf .dart_tool

ios 디렉터리에서

cd ios
rm -rf Pods
rm -rf Podfile.lock
rm -rf .symlinks
rm -rf Flutter/Flutter.framework
rm -rf Flutter/Flutter.podspec
pod deintegrate
pod repo update
pod install --verbose
cd ..

다시 빌드

flutter pub get
flutter build ios --debug
  • pod repo update는 느리지만, spec이 꼬였을 때 효과가 큽니다.
  • CI에서는 pod repo update를 매번 하면 시간이 늘어나므로, 문제가 있을 때만 수행하거나 CocoaPods CDN을 신뢰하는 방식으로 최적화합니다.

2) platform :ios 최소 버전 불일치

가장 흔한 패턴 중 하나가 “어떤 Pod가 더 높은 iOS 버전을 요구한다”는 에러입니다.

예시 로그(형태만 참고):

  • required a higher minimum deployment target

해결

ios/Podfile의 iOS 최소 버전을 올립니다.

platform :ios, '13.0'

여기서 중요한 점:

  • Flutter 플러그인(예: Firebase, GoogleMaps, etc.)이 내부적으로 iOS 최소 버전을 올려버리는 경우가 있습니다.
  • Xcode의 Runner 타깃 Deployment Target과 Podfile의 platform :ios일치시키는 편이 안전합니다.

수정 후:

cd ios
pod install

3) use_frameworks! / use_modular_headers! 충돌

특정 플러그인 조합에서 use_frameworks!가 필요하거나, 반대로 넣으면 충돌하는 경우가 있습니다.

증상

  • Swift 기반 Pod와 Objective-C 기반 Pod가 섞이며 모듈 임포트 에러
  • Include of non-modular header inside framework module 유형

해결 전략

A안: use_frameworks! :linkage => :static 사용

최근 Flutter+iOS 조합에서는 동적 프레임워크보다 정적 링크가 안정적인 경우가 많습니다.

use_frameworks! :linkage => :static
use_modular_headers!

B안: 특정 Pod만 modular header로 강제

플러그인에 따라 다르므로, 문제가 되는 Pod 이름이 로그에 찍히면 그 Pod에만 적용하는 방식도 고려합니다.

팁: 이 단계는 “정답이 하나”가 아니라 플러그인 조합에 따라 달라서, 변경 후 pod install 로그를 기준으로 좁혀야 합니다.

4) Apple Silicon(M1/M2)에서 arm64 관련 이슈

Apple Silicon 환경에서는 시뮬레이터/디바이스 아키텍처가 섞이면서 문제가 생깁니다.

대표 증상

  • 인텔 전용 바이너리/프레임워크가 포함되어 arm64에서 링크 실패
  • 시뮬레이터 빌드에서만 실패

해결: 시뮬레이터에서 arm64 제외(필요한 경우에만)

ios/Podfilepost_install에 아래를 추가합니다.

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/SDK를 Apple Silicon 지원 버전으로 업데이트하는 것이 우선입니다.

5) Ruby gem 에러(ffi, activesupport, xcodeproj)로 pod install 실패

pod install은 Ruby 생태계를 타므로, CocoaPods 자체보다 Ruby 버전/번들러/젬 충돌로 깨지는 경우가 많습니다.

해결 체크리스트

  • 시스템 Ruby 대신 rbenv 또는 asdf로 Ruby 버전을 고정
  • 프로젝트별로 Bundler를 사용해 CocoaPods 버전까지 고정

예: Bundler로 CocoaPods 고정

ios/Gemfile을 만들고:

source 'https://rubygems.org'

gem 'cocoapods', '~> 1.15'

설치 및 실행:

cd ios
bundle install
bundle exec pod install

이렇게 하면 팀원/CI에서 pod 버전 차이로 발생하는 변동을 크게 줄일 수 있습니다.

6) Podfile.lock / Pods 샌드박스 불일치

증상

  • The sandbox is not in sync with the Podfile.lock

해결

대부분 아래로 해결됩니다.

cd ios
pod deintegrate
rm -rf Pods Podfile.lock
pod install

그리고 팀 프로젝트라면:

  • Podfile.lock을 커밋할지 정책을 정합니다.
    • 앱 프로젝트는 보통 커밋(재현성 증가)
    • 플러그인/라이브러리 성격이면 정책이 달라질 수 있음

7) Xcode 버전 업 후 빌드가 갑자기 깨질 때

Xcode 업데이트 후에는 iOS SDK/빌드 시스템 변화로 CocoaPods가 영향을 받습니다.

점검 순서

  1. flutter doctor -v로 Xcode 경로 확인
  2. pod --version 확인
  3. pod repo update 후 재설치
  4. 필요하면 CocoaPods 업그레이드 또는 Bundler 고정

특히 “어제까지 되던 게 오늘 안 됨” 류는 캐시/버전 문제일 확률이 높습니다. 이런 유형의 디버깅 접근은 Next.js 14 RSC 캐시 꼬임으로 갱신이 안될 때처럼 “상태가 남는 시스템”에서 공통적으로 유효합니다.

8) 실전용: 무조건 재현 가능한 진단 루틴

원인을 빨리 좁히려면 “한 번에 다 바꾸기”보다, 아래처럼 관측 가능한 단계로 나누는 게 좋습니다.

1단계: CocoaPods만 단독으로 성공시키기

cd ios
pod install --verbose
  • 여기서 실패하면 Flutter가 아니라 iOS/Ruby/CocoaPods 레이어 문제입니다.

2단계: 워크스페이스로 Xcode 빌드

Runner.xcworkspace를 열고 Runner를 빌드합니다.

  • 여기서 실패하면 Pod 통합은 됐지만 Xcode 설정/아키텍처/링커 문제일 수 있습니다.

3단계: Flutter 빌드로 재확인

cd ..
flutter build ios --debug -v
  • -v 로그로 어떤 단계에서 깨지는지 확인합니다.

9) 자주 쓰는 Podfile 템플릿(안전한 형태)

프로젝트마다 다르지만, “기본 뼈대”로는 아래 형태가 무난합니다.

platform :ios, '13.0'

# CocoaPods 통합 옵션은 프로젝트 상황에 맞게 조정
# use_frameworks! :linkage => :static
# use_modular_headers!

install! 'cocoapods', :disable_input_output_paths => true

target 'Runner' do
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    # Apple Silicon 시뮬레이터 이슈가 있을 때만 사용
    # target.build_configurations.each do |config|
    #   config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
    # end
  end
end

포인트:

  • post_install에서 Flutter가 주입하는 flutter_additional_ios_build_settings(target)는 유지하는 편이 안전합니다.
  • EXCLUDED_ARCHS는 필요할 때만 켜고, 가능하면 SDK 업데이트로 제거하는 것을 목표로 합니다.

10) 마무리: “Podfile 오류”를 빠르게 끝내는 핵심

  • 먼저 Pods/Podfile.lock/.symlinks를 지우고 pod deintegrate완전 초기화합니다.
  • 그 다음 platform :ios 최소 버전 불일치를 해결합니다.
  • Apple Silicon이면 arm64 이슈를 의심하고, 우회는 최소화합니다.
  • Ruby/CocoaPods 버전은 Bundler로 고정해 팀/CI 재현성을 확보합니다.

iOS 빌드는 한 번 꼬이면 원인이 여러 층에 걸쳐 보이기 때문에, 로그를 “한 줄”만 보고 단정하기 어렵습니다. 위 루틴대로 레이어를 분리해서 확인하면 Podfile 계열 문제는 대부분 빠르게 정리됩니다.