Published on

Flutter iOS 빌드 No such module 오류 해결 가이드

Authors

서론

Flutter iOS 빌드에서 No such module 'XXX'는 단순히 “모듈이 없다”는 의미로 끝나지 않습니다. 대부분은 CocoaPods 통합 상태 불일치, Xcode가 열어야 할 대상(Workspace/Project) 혼동, Pod 캐시/DerivedData 오염, 정적/동적 프레임워크 설정 충돌, 아키텍처(특히 Apple Silicon) 문제 중 하나로 귀결됩니다.

이 글은 에러 메시지에 휘둘리지 않고, “지금 내 프로젝트가 어떤 상태인지”를 빠르게 진단해 재빌드 가능한 정상 상태로 되돌리는 절차를 제공합니다. 빌드 시스템 문제를 체계적으로 다루는 관점은 Next.js 빌드 장애를 다룬 글(Next.js 14 빌드 OOM·느려짐 해결 - SWC 캐시·메모리 튜닝)과도 유사합니다. 핵심은 캐시/의존성/빌드 설정의 일관성입니다.


에러가 의미하는 것: Xcode가 모듈을 찾는 경로

Swift/ObjC에서 No such module은 보통 아래 중 하나가 깨졌다는 신호입니다.

  1. Pod가 설치되지 않았거나(Pods 폴더/Lockfile 불일치)
  2. Xcode가 Pods가 포함된 Workspace가 아니라 Project를 열었거나
  3. Build Settings의 Framework Search Paths / Header Search Paths가 꼬였거나
  4. 모듈이 생성되었지만 캐시/인덱스가 오래된 상태(DerivedData)

Flutter에서는 여기에 추가로:

  • ios/Podfile의 설정 변경(예: use_frameworks!, use_modular_headers!)이 플러그인과 충돌
  • flutter clean만으로는 해결되지 않는 CocoaPods 캐시 문제
  • Apple Silicon에서 시뮬레이터/디바이스 아키텍처 혼선

이 조합으로 “어제는 됐는데 오늘 안 됨”이 흔히 발생합니다.


1단계: 가장 흔한 원인 — Workspace/Project 혼동

Flutter iOS는 CocoaPods를 쓰므로, Xcode에서 열어야 할 것은 보통 다음입니다.

  • 올바름: ios/Runner.xcworkspace
  • 흔한 실수: ios/Runner.xcodeproj

Xcode로 직접 빌드할 때 Runner.xcodeproj를 열면 Pods가 링크되지 않아 No such module 'Firebase', No such module 'GoogleMaps' 같은 오류가 뜹니다.

빠른 체크

  • Xcode 좌측 Project Navigator에 Pods 프로젝트가 보이는가?
  • Runner.xcworkspace로 열었는가?

CLI로만 빌드한다면(예: flutter build ios) 보통 이 문제는 덜하지만, 중간에 Xcode에서 project 파일을 열고 설정을 저장하면 꼬일 수 있습니다.


2단계: CocoaPods 재동기화(대부분의 케이스 해결)

가장 재현성 높은 복구 루틴은 “Flutter 캐시 + Pods + DerivedData”를 일관되게 초기화한 뒤 다시 설치하는 것입니다.

아래 순서대로 실행하세요.

# 프로젝트 루트
flutter clean

# iOS 의존성 재생성
rm -rf ios/Pods ios/Podfile.lock

# Xcode 캐시(선택이지만 강력 추천)
rm -rf ~/Library/Developer/Xcode/DerivedData

# Flutter 패키지 재동기화
flutter pub get

# CocoaPods 재설치
cd ios
pod repo update
pod install
cd ..

# 빌드 확인
flutter build ios -v

Podfile.lock까지 지우나?

Podfile.lock은 “설치된 정확한 버전 스냅샷”입니다. 플러그인 버전이 바뀌었거나, 로컬 Pod 캐시가 꼬였거나, Xcode 버전이 바뀐 경우 lock과 실제 Pods 상태가 어긋나며 모듈 생성이 실패할 수 있습니다.

> 팀 프로젝트에서 무조건 lock을 지우는 건 정책에 따라 다릅니다. CI/협업 환경이라면 먼저 pod deintegrate + pod install을 시도하고, 그래도 안 되면 lock 제거를 고려하세요.


3단계: use_frameworks! / use_modular_headers! 충돌 점검

Flutter 플러그인 중 일부는 정적 라이브러리/모듈 헤더 방식에 민감합니다. 특히 Firebase 계열, GoogleMaps 계열, Swift 기반 Pod 조합에서 use_frameworks! 설정에 따라 모듈 생성 방식이 달라지고, 결과적으로 No such module이 발생할 수 있습니다.

Podfile에서 확인할 포인트

ios/Podfile의 상단 또는 target 블록에 아래 설정이 있는지 확인하세요.

platform :ios, '13.0'

# 문제가 되는 경우가 있는 옵션들
# use_frameworks!
# use_modular_headers!

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

실전 팁

  • 과거에 use_frameworks!를 추가했다면, 플러그인/Pod 조합에 따라 오히려 깨질 수 있습니다.
  • 반대로 어떤 플러그인은 Swift 모듈 때문에 use_frameworks!가 필요할 때도 있습니다.

즉, “무조건 넣어라/빼라”가 아니라 최근 추가한 플러그인과 함께 변경 이력을 보고 결정해야 합니다.

post_install에서 iOS 설정을 강제하는 경우

일부 템플릿/가이드에서 post_install로 빌드 설정을 강제합니다. 여기서 EXCLUDED_ARCHS, IPHONEOS_DEPLOYMENT_TARGET 등을 잘못 건드리면 모듈 빌드가 누락될 수 있습니다.

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      # 예: Apple Silicon 관련 임시 설정이 남아있는지 확인
      # config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
    end
  end
end

4단계: Apple Silicon(arm64) 시뮬레이터 이슈

M1/M2/M3 환경에서 특정 Pod가 시뮬레이터 arm64를 제대로 지원하지 않으면,

  • Pod 빌드가 실패하거나
  • 모듈이 생성되지 않아 결과적으로 No such module로 보일 수 있습니다(근본 원인은 상위 로그에 존재).

해결 접근

  1. 먼저 flutter build ios -v 또는 Xcode 빌드 로그에서 진짜 최초 실패 지점을 찾습니다.
  2. 해당 Pod가 시뮬레이터 arm64를 지원하지 않는다면 임시로 제외할 수 있습니다.
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 업데이트로 해결되는 경우가 많으므로 pod repo update 및 해당 라이브러리 최신 버전을 우선 확인하세요.


5단계: 모듈 캐시/인덱스 오염(특히 Xcode 업데이트 직후)

Xcode 업데이트 후 No such module이 갑자기 발생하면, 모듈 캐시/DerivedData 불일치가 원인일 확률이 큽니다.

권장 초기화

rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Caches/CocoaPods

그리고 pod install을 다시 수행합니다.

빌드 시스템 이슈는 “캐시를 지우면 왜 되지?”로 끝나기 쉬운데, 실제로는 빌드 그래프가 캐시된 산출물에 의존하기 때문에, 산출물 버전이 어긋나면 모듈 로딩이 실패합니다. 이런 유형은 다른 생태계에서도 자주 보이며, 예를 들어 캐시 튜닝 관점은 Next.js 14 빌드 OOM·느려짐 해결 - SWC 캐시·메모리 튜닝에서도 비슷한 맥락으로 설명할 수 있습니다.


6단계: CI에서만 터지는 경우(경로/환경 차이)

로컬에서는 되는데 CI에서 No such module이 뜬다면 대개 다음이 원인입니다.

  • CI에 CocoaPods가 없거나 버전이 다름
  • pod install이 실행되지 않음
  • Ruby/Bundler 환경 차이
  • 캐시 복원 전략이 잘못되어 Pods/DerivedData가 섞임

권장: Bundler로 CocoaPods 버전 고정

ios/Gemfile을 두고 CI에서 bundle exec pod install을 사용하면 재현성이 올라갑니다.

# ios/Gemfile
source 'https://rubygems.org'

gem 'cocoapods', '1.15.2'
cd ios
bundle install
bundle exec pod install

CI 장애는 “환경이 다르다”가 본질이므로, EKS에서 네트워크/엔드포인트 차이로 장애가 나는 케이스처럼 원인 분리를 먼저 해야 합니다(접근 방식 자체는 EKS STS 엔드포인트 타임아웃 - VPC·NAT·DNS 해결 같은 글의 진단 흐름과 유사합니다).


7단계: 그래도 안 되면 — 실패한 Pod를 특정하는 방법

No such module은 결과일 뿐이라, 실제 실패는 그 이전에 있습니다.

1) verbose 로그로 최초 에러 찾기

flutter build ios -v 2>&1 | tee build.log
# build.log에서 "error:"가 처음 등장하는 위치를 찾는다

2) Xcode에서 Pods 타깃 빌드 확인

  • Runner.xcworkspace 열기
  • Scheme을 Runner로 두고 빌드
  • 좌측에서 Pods 프로젝트의 해당 타깃이 실패하는지 확인

3) 자주 보이는 근본 원인 예시

  • Swift 버전/Deployment Target 불일치
  • 특정 Pod가 새 Xcode/새 iOS SDK에서 컴파일 실패
  • OTHER_LDFLAGS 충돌로 링크 실패 후 모듈 생성 누락

이 경우는 “No such module”만 고치려 하지 말고, 해당 Pod의 컴파일 에러를 먼저 해결해야 합니다.


체크리스트(요약)

  • Xcode는 Runner.xcworkspace로 열었는가?
  • flutter clean + Pods/Podfile.lock 제거 후 pod install을 다시 했는가?
  • DerivedData/CocoaPods 캐시를 초기화했는가?
  • use_frameworks!/use_modular_headers! 변경 이력이 있는가?
  • Apple Silicon 시뮬레이터 arm64 이슈가 아닌가?
  • flutter build ios -v에서 최초 실패 Pod를 찾았는가?
  • CI라면 CocoaPods 버전을 Bundler로 고정했는가?

결론

Flutter iOS의 No such module은 대부분 “모듈이 없다”가 아니라 Pods 통합이 깨졌다는 신호입니다. 가장 빠른 해결은 (1) Workspace 확인, (2) Pods/Lock/DerivedData를 포함한 재동기화, (3) Podfile 옵션 충돌 점검의 3단계를 순서대로 밟는 것입니다.

그래도 해결되지 않는다면, verbose 로그에서 최초로 실패한 Pod의 컴파일 에러를 잡아내는 것이 정공법입니다. No such module은 마지막에 나타나는 증상일 뿐, 진짜 원인은 그 위에 있습니다.