Published on

Flutter iOS 빌드 No such module 오류 해결법

Authors

서론

Flutter로 iOS 빌드를 하다 보면 어느 날 갑자기 No such module 'XXX' 혹은 Module 'XXX' not found 같은 오류가 튀어나옵니다. 특히 플러그인을 추가/삭제했거나, Xcode 버전을 올렸거나, CocoaPods를 업데이트했거나, CI에서만 실패하는 경우에 자주 발생합니다. 이 오류는 “모듈이 실제로 없는” 상황도 있지만, 대부분은 Pod 설치 상태/빌드 설정/캐시/워크스페이스 선택이 꼬여서 Xcode의 Swift 모듈 탐색 경로가 깨진 케이스입니다.

이 글에서는 원인을 몇 가지 범주로 나눠 가장 빠르게 복구하는 체크리스트와, 재발 방지를 위한 설정까지 정리합니다. (같은 주제를 더 짧게 요약한 글이 필요하면 Flutter iOS 빌드 No such module 오류 해결 가이드도 참고하세요.)

1) 오류 메시지부터 원인 범주를 나누기

No such module은 보통 아래 중 하나로 귀결됩니다.

  1. Pods 자체가 설치/연결되지 않음
    • .xcworkspace가 아닌 .xcodeproj를 열었거나
    • pod install이 실패/미실행/다른 Ruby 환경에서 실행됨
  2. Pod는 설치됐지만 Swift 모듈로 import 불가
    • use_frameworks!/use_modular_headers! 영향
    • DEFINES_MODULE, CLANG_ENABLE_MODULES 설정 문제
  3. 캐시/DerivedData/Pod 캐시가 꼬임
    • Xcode 인덱스/빌드 캐시가 오래된 상태
  4. 아키텍처/플랫폼 불일치
    • 시뮬레이터에서만 실패(arm64/x86_64)
    • iOS Deployment Target 불일치
  5. Flutter 플러그인/Podspec의 버전 충돌
    • Podfile.lockpubspec.lock 조합이 깨짐

먼저 어떤 케이스인지 좁히면 시간 낭비를 크게 줄입니다.

2) 가장 먼저 확인할 3가지 (대부분 여기서 끝)

2.1 .xcworkspace로 열고 있는지 확인

CocoaPods를 쓰는 iOS 프로젝트는 반드시 Runner.xcworkspace로 열어야 합니다.

  • 올바른 파일: ios/Runner.xcworkspace
  • 잘못된 파일: ios/Runner.xcodeproj

Xcode 상단에서 프로젝트 네비게이터가 Pods 프로젝트를 포함하는지 확인하세요. 없다면 거의 확실히 워크스페이스를 안 연 겁니다.

2.2 iOS 폴더에서 Pods 재설치

가장 흔한 복구 루틴입니다.

# 프로젝트 루트에서
flutter clean
rm -rf ios/Pods ios/Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData

flutter pub get

cd ios
pod repo update
pod install
cd ..

flutter build ios
  • DerivedData 삭제는 “Xcode는 여전히 예전 모듈을 찾는” 상황을 끊어주는 데 효과가 큽니다.
  • pod repo update는 spec repo가 오래돼서 특정 버전 해석이 꼬일 때 도움이 됩니다.

2.3 CocoaPods 실행 환경이 일관적인지 확인

회사 맥/개인 맥/CI에서 Ruby 환경이 다르면 pod install 결과가 달라질 수 있습니다. 아래로 현재 CocoaPods 버전을 확인합니다.

pod --version
ruby -v
which pod

Bundler를 쓰는 프로젝트라면(권장) 아래처럼 고정하세요.

cd ios
bundle exec pod install

3) Swift 모듈로 import가 안 되는 케이스: use_frameworks! / modular headers

오류가 예를 들어 아래처럼 뜬다고 가정해봅시다.

  • No such module 'FirebaseCore'
  • No such module 'GoogleMaps'
  • No such module 'SomePod'

Pods 폴더에 소스는 있는데 Swift가 모듈로 인식하지 못하는 경우가 있습니다.

3.1 Podfile에서 use_frameworks!의 부작용 점검

Flutter 플러그인 조합에 따라 use_frameworks!가 필요하거나(특히 Swift 기반) 오히려 문제를 만들기도 합니다.

대표적으로 다음 조합에서 이슈가 납니다.

  • 어떤 Pod는 정적 라이브러리(static)로 링크되길 기대
  • 어떤 Pod는 동적 프레임워크(dynamic framework)로 빌드되길 기대
  • 결과적으로 Swift 모듈 생성/탐색이 어긋남

가능하면 Flutter 기본 템플릿에 가까운 Podfile로 유지하고, 필요 시에만 옵션을 추가하세요.

예시(상황에 따라):

# ios/Podfile
platform :ios, '13.0'

# Flutter 기본 설정
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

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

  # 필요할 때만 시도
  # use_frameworks!
  # use_modular_headers!
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end
  • 이미 use_frameworks!를 쓰고 있고 갑자기 No such module이 늘었다면, 일단 주석 처리 후 재설치를 해보세요.
  • 반대로 특정 Swift Pod가 모듈로 안 잡히면 use_frameworks! 또는 use_modular_headers!가 필요할 수 있습니다. 이 경우 “특정 Pod만” 프레임워크로 만드는 세밀한 제어가 필요하지만, Flutter 프로젝트에서는 플러그인/Pod 조합에 따라 부작용이 커서 우선은 공식 권장 조합을 따르는 편이 안전합니다.

3.2 Xcode Build Settings에서 모듈 관련 플래그 확인

Runner 타겟과 문제가 되는 Pod 타겟에서 아래 값이 예상대로인지 봅니다.

  • CLANG_ENABLE_MODULES = YES
  • DEFINES_MODULE = YES (특정 Pod에서 필요)

대개는 CocoaPods가 자동 설정하지만, 수동으로 값을 바꿨거나 오래된 프로젝트를 업그레이드한 경우 깨질 수 있습니다.

4) 시뮬레이터에서만 실패하는 경우: 아키텍처(arm64/x86_64) 문제

Apple Silicon(M1/M2/M3) 환경에서 특히 흔합니다.

  • 디바이스 빌드는 성공
  • iOS Simulator 빌드는 No such module 또는 링크 에러로 실패

4.1 Pod가 시뮬레이터 arm64를 지원하는지 확인

일부 바이너리 Pod는 특정 아키텍처를 제공하지 않습니다. 이때는 임시로 Excluded Architectures를 적용하기도 합니다.

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      # 시뮬레이터에서 arm64 제외(필요할 때만)
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
    end
  end
end

주의:

  • 이 설정은 “모든 문제의 만능키”가 아니라, 특정 Pod의 바이너리/아키텍처 제약을 우회하는 용도입니다.
  • 최근 Pod들은 arm64 simulator를 지원하는 경우가 많아, 무조건 넣으면 오히려 성능/호환성에 악영향이 있을 수 있습니다.

5) iOS Deployment Target 불일치로 인한 연쇄 오류

platform :ios, '12.0'인데 어떤 Pod는 iOS 13+를 요구하면, 설치는 되더라도 빌드 단계에서 모듈 생성이 깨지는 형태로 오류가 나타나기도 합니다.

5.1 Podfile과 Xcode의 타겟 버전을 맞추기

  • Podfile platform :ios, '13.0' (예)
  • Xcode > Runner target > Deployment Info도 동일하게

변경 후에는 반드시 Pods 재설치를 동반하세요.

cd ios
rm -rf Pods Podfile.lock
pod install

6) 플러그인 추가/삭제 후 lock 충돌: pubspec.lock과 Podfile.lock 동기화

Flutter 플러그인을 바꾸면 iOS 쪽 Pod 종속성도 바뀝니다. 그런데 아래 상태가 되면 “실제로는 필요한 Pod가 있는데 Xcode가 못 찾는” 상황이 생깁니다.

  • pubspec.lock은 최신
  • Podfile.lock은 예전
  • Pods 폴더는 중간 상태

권장 루틴:

flutter clean
flutter pub get
cd ios
pod deintegrate
pod install
cd ..

pod deintegrate는 기존 Pods 통합 흔적을 제거해 “중간 상태”를 확실히 정리합니다.

7) CI에서만 실패할 때 체크리스트

로컬에서는 되는데 CI에서만 No such module이 뜨면, 대부분 다음 중 하나입니다.

  • Xcode 버전/Command Line Tools 버전 차이
  • CocoaPods 버전 차이
  • 캐시(특히 Pods 캐시) 재사용 방식 문제
  • flutter pub get/pod install 실행 순서 문제

권장 순서(예: GitHub Actions 등):

flutter --version
flutter pub get

cd ios
pod --version
pod repo update
pod install --verbose
cd ..

flutter build ios --release

또한 CI 캐시를 쓴다면 ios/Pods를 통째로 캐시하기보다, CocoaPods 캐시는 신중히 다루는 편이 안전합니다(프로젝트/플러그인 변경에 취약).

8) 그래도 안 되면: 원인 추적을 위한 로그 포인트

해결이 안 될 때는 “모듈이 어디서 생성되어야 하는가/어디서 찾고 있는가”를 확인해야 합니다.

  1. Xcode 빌드 로그에서 -I(헤더 검색 경로), -F(프레임워크 검색 경로) 확인
  2. Pods/Target Support Files/<PodName>/<PodName>.xcconfig 존재 여부 확인
  3. ios/Pods/에 해당 모듈이 실제로 있는지 확인
  4. pod install --verbose로 설치 과정에서 경고/에러가 있었는지 확인

특히 pod install이 조용히 실패하거나(네트워크/권한), 스펙 해석이 꼬여 다른 버전이 설치되면 빌드 단계에서만 터집니다.

9) 결론: 가장 재현성 높은 해결 순서

대부분의 No such module은 아래 5단계로 해결됩니다.

  1. Runner.xcworkspace로 열기
  2. flutter clean + DerivedData 삭제
  3. ios/Pods, ios/Podfile.lock 삭제 후 pod install
  4. pod deintegrate까지 포함해 완전 재통합
  5. (시뮬레이터 한정) 아키텍처/Deployment Target 불일치 점검

이 에러는 “한 번 해결하면 끝”이 아니라, 플러그인/툴체인 업데이트 때 다시 나타날 수 있습니다. 따라서 팀/CI에서 재현 가능한 스크립트로 표준화하는 것이 가장 큰 예방책입니다.

추가로, 환경/의존성 꼬임을 빠르게 진단하는 접근은 Python의 ModuleNotFoundError 문제를 푸는 사고방식과도 유사합니다. 원인 분류와 체크리스트식 접근이 필요하다면 pip install은 성공인데 실행하면 ModuleNotFoundError가 뜰 때 venv poetry conda 혼용으로 꼬인 인터프리터와 site-packages를 10분 만에 진단하고 확실히 고치는 체크리스트도 함께 읽어보면 도움이 됩니다.