Published on

Flutter iOS 빌드 No such module Flutter 해결법

Authors

Flutter로 iOS 빌드를 하다 보면 Xcode에서 No such module Flutter 에러가 갑자기 터지는 경우가 있습니다. 보통은 Flutter 엔진/프레임워크가 iOS 프로젝트에 정상적으로 링크되지 않았거나, CocoaPods가 생성해야 할 설정 파일이 누락되었거나, Xcode가 잘못된 프로젝트를 열고 있는 상황에서 발생합니다.

이 글에서는 원인을 크게 몇 가지로 분류하고, 각 케이스에서 가장 빠르게 복구하는 방법을 순서대로 제시합니다. 팀/CI 환경에서도 재발을 줄일 수 있도록 “왜 그런지”까지 함께 정리합니다.

에러가 의미하는 것

No such module Flutter는 Swift/Objective-C 컴파일 단계에서 Flutter 모듈을 임포트할 수 없다는 뜻입니다. 즉, 아래 중 하나가 깨졌다는 신호입니다.

  • Pods 또는 Flutter 관련 xcconfig가 생성되지 않았거나 경로가 꼬임
  • Xcode가 .xcodeproj를 열어 Pods 통합이 적용되지 않음(워크스페이스 미사용)
  • Podfile 설정 문제로 Flutter.framework/Flutter.xcframework가 링크 대상에서 누락
  • 캐시/DerivedData 또는 Pods 캐시 불일치
  • 여러 플러터 버전/여러 Xcode 설정이 섞여서 빌드 설정이 오염

가장 먼저 확인할 2가지(체크리스트)

1) Xcode에서 반드시 .xcworkspace를 열기

CocoaPods를 쓰는 iOS 프로젝트는 항상 Runner.xcworkspace로 열어야 합니다.

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

Runner.xcodeproj를 열면 Pods가 연결되지 않아 Flutter 모듈을 못 찾는 경우가 많습니다.

2) iOS 디렉터리에서 Pods가 정상 설치되어 있는지

ios/Pods 폴더가 없거나, ios/Flutter/Generated.xcconfig가 없다면 통합이 깨진 상태일 확률이 큽니다.

다음 파일/폴더 존재 여부를 확인하세요.

  • ios/Pods/
  • ios/Podfile.lock
  • ios/Flutter/Generated.xcconfig
  • ios/Runner.xcworkspace

80%는 이걸로 끝: 클린 + Pods 재설치

아래는 가장 범용적인 복구 절차입니다. 로컬에서 한 번에 정리하려면 그대로 실행하세요.

# 프로젝트 루트에서
flutter clean

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

flutter pub get

cd ios
pod repo update
pod install
cd ..

# Xcode 빌드 캐시까지 정리(선택)
rm -rf ~/Library/Developer/Xcode/DerivedData

이후 ios/Runner.xcworkspace를 열고 빌드합니다.

open ios/Runner.xcworkspace

왜 이게 먹히나

Flutter iOS 빌드는 CocoaPods가 생성하는 설정 파일과 스크립트에 강하게 의존합니다. flutter clean만으로는 Pods 쪽 잔여물이 남는 경우가 있어, PodsPodfile.lock를 함께 지우고 재설치하면 모듈 임포트 경로가 다시 정렬됩니다.

Podfile 설정 점검(특히 use_frameworks!)

플러그인 조합에 따라 Podfile 옵션이 iOS 빌드를 깨뜨릴 수 있습니다. 대표적으로 use_frameworks! 사용 시, 일부 구성에서 모듈 로딩이 꼬이거나 Swift 모듈맵이 예상과 다르게 생성될 수 있습니다.

ios/Podfile에서 다음을 점검하세요.

  • Flutter 기본 템플릿의 flutter_install_all_ios_pods 호출이 유지되는지
  • platform :ios, 'xx.x'가 너무 낮지 않은지(플러그인 최소 버전 요구)
  • use_frameworks! 또는 use_modular_headers!를 추가했다면 그 의도를 재검토

예시(기본에 가까운 형태):

platform :ios, '13.0'

# CocoaPods 통합
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)
  end
end

만약 특정 플러그인 때문에 use_frameworks!가 필요하다면, 아래처럼 명시적으로 linkage를 조정하는 방식이 충돌을 줄이는 데 도움이 되기도 합니다.

use_frameworks! :linkage => :static

다만 이 설정은 플러그인/프로젝트 구성에 따라 결과가 달라서, 적용 후에는 반드시 클린 빌드로 검증해야 합니다.

Generated.xcconfig 누락/미생성 문제

에러 로그를 보면 ios/Flutter/Generated.xcconfig를 못 찾는 식의 메시지가 같이 뜨는 경우가 있습니다. 이 파일은 flutter pub get 또는 iOS 빌드 과정에서 생성됩니다.

다음 순서로 재생성하세요.

flutter pub get
flutter build ios --debug

그래도 생성되지 않는다면, 프로젝트 루트에서 Flutter SDK 경로가 깨졌거나(예: FVM 전환), 권한/경로 문제로 생성이 실패했을 수 있습니다.

Xcode Build Settings에서 모듈 검색 경로가 꼬인 경우

간헐적으로 Xcode 설정이 오염되면 Framework Search PathsOther Linker Flags가 이상한 값으로 남아 빌드를 망칠 수 있습니다.

  • Runner 타깃의 Build Settings에서 Flutter를 수동으로 추가한 흔적이 있다면 제거
  • Pods-Runner 관련 설정이 비정상적으로 삭제/변경되었다면 Pods 재설치로 복원

이 경우도 대부분은 “Pods 재설치 + 워크스페이스 열기”로 해결됩니다.

Apple Silicon(M1/M2)에서 CocoaPods/루비 아키텍처 이슈

M 시리즈 맥에서 Ruby/CocoaPods가 x86_64로 설치되어 있거나, 반대로 프로젝트가 arm64 기준으로만 맞춰져 있으면 Pods 설치는 되는데 빌드가 깨지는 경우가 있습니다.

다음 중 하나로 정리합니다.

  • Homebrew/Ruby/CocoaPods를 arm64로 통일
  • 필요 시 Rosetta로 pod install 실행

예:

arch -arm64 pod install
# 또는
arch -x86_64 pod install

어느 쪽이 맞는지는 로컬의 Ruby/CocoaPods 설치 상태에 따라 다르므로, 팀에서는 가능한 한 개발 환경을 통일하거나 bundle exec pod install로 버전 고정을 권장합니다.

CI에서만 터질 때: 캐시 전략과 재현성

로컬에서는 되는데 CI에서만 No such module Flutter가 뜬다면, 대개 캐시된 Pods/DerivedData가 원인입니다.

  • ios/Pods를 캐시하더라도 Podfile.lock과 강하게 묶어서 캐시 키를 구성
  • Flutter SDK 버전이 바뀌면 iOS 쪽 캐시를 무효화
  • 빌드 단계에서 최소한 아래는 보장
flutter --version
flutter pub get
cd ios && pod install && cd ..
flutter build ios --release

문제 추적 방식은 인프라 장애를 좁혀가는 방식과 유사합니다. 증상을 빠르게 분리하고 원인을 압축하는 접근은 아래 글의 트러블슈팅 흐름도 참고할 만합니다.

플러터 버전/FVM 전환 후 자주 발생하는 케이스

FVM을 쓰거나 Flutter 채널을 바꾼 직후에 이 에러가 나면, 기존에 생성된 iOS 아티팩트가 새 SDK와 맞지 않는 경우가 많습니다.

권장 루틴:

fvm flutter clean
rm -rf ios/Pods ios/Podfile.lock
fvm flutter pub get
cd ios && pod install && cd ..

또한 Xcode에서 Runner 스킴이 예전 빌드 산출물을 바라보고 있지 않은지 확인하고, DerivedData를 한 번 지우는 것이 안전합니다.

그래도 안 되면: 최소 재현으로 원인 분리

여기까지 했는데도 해결이 안 되면, “플러그인 문제”인지 “프로젝트 iOS 설정 문제”인지 분리해야 합니다.

  1. 새 Flutter 프로젝트 생성
flutter create tmp_flutter_ios
cd tmp_flutter_ios
flutter build ios --debug
  1. 새 프로젝트는 되는데 기존만 안 되면
  • 최근 추가/업데이트한 플러그인부터 의심
  • Podfile 커스텀 설정을 원복해가며 확인
  • ios/Runner.xcodeproj 내부 수동 변경 이력 확인
  1. 새 프로젝트도 안 되면
  • 로컬 CocoaPods/Xcode 설치 상태 문제일 확률이 높음

이 과정은 Git에서 충돌을 자동 해결하기 위해 재현 조건을 줄여나가는 것과 비슷합니다. 복잡한 변경 이력을 다룰 때는 아래 글의 접근도 도움이 됩니다.

결론: 해결 우선순위 요약

No such module Flutter는 대부분 아래 순서로 해결됩니다.

  1. Xcode에서 Runner.xcworkspace를 열었는지 확인
  2. flutter clean + Pods/Podfile.lock 삭제 후 pod install
  3. Generated.xcconfig 재생성(flutter pub get, flutter build ios)
  4. Podfileuse_frameworks! 등 커스텀 옵션 점검
  5. Apple Silicon 아키텍처/Ruby/CocoaPods 환경 통일
  6. CI 캐시 무효화 및 Flutter 버전 변경 시 캐시 키 재설계

한 번 해결하고 끝내기보다, 팀에서는 Podfile.lock 관리, Flutter 버전 고정(FVM), 그리고 CI에서의 캐시 키 설계를 통해 재발을 줄이는 것이 가장 효과적입니다.