Published on

Flutter iOS 빌드 No such module Flutter 해결법

Authors

서론

Flutter로 iOS 빌드를 하다 보면 갑자기 Xcode가 아래와 같은 에러를 뿜는 순간이 있습니다.

  • No such module 'Flutter'
  • Module 'Flutter' not found
  • Flutter/Flutter.h file not found

대부분은 iOS 쪽 의존성(Pods) 통합이 깨졌거나, Flutter 엔진/프레임워크 산출물(Generated.xcconfig, Flutter.framework 등)이 생성되지 않았거나, Xcode에서 열어야 할 파일을 잘못 열었거나(.xcodeproj vs .xcworkspace) 같은 “환경/빌드 파이프라인” 문제입니다.

이 글은 원인별로 증상을 분류하고, 가장 적은 시행착오로 정상 빌드 상태로 되돌리는 절차를 체크리스트 형태로 제공합니다. (원인 분석을 할 때는 장애 진단 글처럼 ‘재현 → 관찰 → 최소 변경 → 검증’ 흐름이 중요합니다. 비슷한 접근으로는 K8s CrashLoopBackOff - Readiness·Liveness 5분 진단 같은 글의 방식도 참고할 만합니다.)


에러가 의미하는 것: iOS 타깃에서 Flutter 모듈을 못 찾는다

No such module Flutter는 Swift/Obj-C 컴파일 단계에서 Flutter라는 모듈(프레임워크)을 import 할 수 없다는 뜻입니다.

대표적으로 다음 상황에서 발생합니다.

  1. CocoaPods 통합이 깨짐: Pods 프로젝트/설정이 꼬여서 Flutter 프레임워크가 링크/검색 경로에 없음
  2. Flutter iOS 산출물 미생성: ios/Flutter/Generated.xcconfig 등이 없거나 오래된 상태
  3. Xcode에서 잘못된 엔트리로 빌드: .xcworkspace 대신 .xcodeproj를 열어서 Pods 설정이 적용되지 않음
  4. Podfile/빌드 설정 충돌: use_frameworks!, modular_headers, SWIFT_VERSION, EXCLUDED_ARCHS 등으로 모듈 맵이 꼬임
  5. 캐시/DerivedData 오염: Xcode 캐시가 오래된 빌드 아티팩트를 참조

이제 “가장 흔한 것부터” 순서대로 해결합니다.


1) 가장 먼저 확인: .xcworkspace로 열었는가?

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

  • 잘못: ios/Runner.xcodeproj 열기
  • 올바름: ios/Runner.xcworkspace 열기

.xcodeproj로 빌드하면 Pods가 붙지 않기 때문에 Flutter 모듈을 못 찾는 케이스가 매우 흔합니다.

빠른 점검

터미널에서 아래 파일이 존재하는지 확인합니다.

ls ios/Runner.xcworkspace

없다면 Pods 설치가 안 된 상태일 가능성이 큽니다. 다음 섹션으로 넘어가세요.


2) Generated.xcconfig가 없거나 오래된 경우: flutter pub get부터

Flutter iOS 빌드의 핵심 설정은 ios/Flutter/Generated.xcconfig에 생성됩니다. 이 파일이 없거나 내용이 깨지면 Xcode가 Flutter 관련 경로를 제대로 잡지 못합니다.

증상

  • ios/Flutter/Generated.xcconfig 파일이 없음
  • CI에서만 실패(로컬에는 남아있던 파일이 CI에는 없음)
  • Flutter.framework 관련 경로가 비어있음

해결 절차

프로젝트 루트에서 다음 순서로 실행합니다.

flutter clean
flutter pub get

그 다음 iOS 폴더로 이동해 Pods를 재설치합니다.

cd ios
pod deintegrate
pod install
cd ..

마지막으로 다시 빌드합니다.

flutter build ios --debug
# 또는
flutter run

> 포인트: flutter pub get이 먼저입니다. pod install은 Generated.xcconfig를 참조하기 때문에 순서가 뒤집히면 또 깨질 수 있습니다.


3) Pods 통합이 깨진 경우: pod install 재생성 + 캐시 정리

특히 Xcode 버전 업그레이드(예: 14 → 15), Flutter 버전 변경, 팀원 간 Podfile.lock 충돌 이후에 자주 발생합니다.

권장 리셋 루틴(안전한 순서)

flutter clean
rm -rf ios/Pods
rm -rf ios/.symlinks
rm -f ios/Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData

flutter pub get
cd ios
pod repo update
pod install
cd ..
  • Pods, .symlinks, Podfile.lock 제거는 “완전 재생성”을 의미합니다.
  • DerivedData 삭제는 Xcode가 오래된 모듈 캐시를 잡고 있는 경우에 효과가 큽니다.

이후 Xcode는 반드시 Runner.xcworkspace로 열고 빌드합니다.


4) Podfile 설정 이슈: use_frameworks!/modular_headers 충돌 점검

No such module Flutter가 “특정 플러그인 추가 이후” 발생했다면 Podfile 설정 충돌일 수 있습니다.

흔한 패턴

  • 어떤 SDK가 use_frameworks!를 요구
  • 다른 일부 플러그인이 정적 링크/모듈 맵과 충돌
  • Swift 모듈 import가 꼬이면서 Flutter 모듈 탐색에도 영향

기본 Podfile 예시(Flutter 템플릿 기반)

아래는 Flutter 기본 구조에서 크게 벗어나지 않는 것이 중요합니다.

platform :ios, '12.0'

# Flutter 기본 설정을 유지하는 것이 안정적입니다.

target 'Runner' do
  use_frameworks! :linkage => :static
  use_modular_headers!

  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

체크 포인트

  • post_install에서 flutter_additional_ios_build_settings(target) 호출이 빠지면 Flutter 관련 빌드 설정이 누락될 수 있습니다.
  • use_frameworks!가 필요 없다면 제거하는 편이 충돌 가능성이 낮습니다.
  • 팀 내에서 Podfile을 수정했다면, 변경 전/후로 pod install 로그에 Flutter 관련 pod가 정상적으로 잡히는지 확인하세요.

5) Xcode Build Settings에서 직접 확인해야 하는 값들

명령어로 리셋해도 안 되면, Xcode에서 “지금 Runner 타깃이 Flutter를 찾도록 설정되어 있는지”를 확인해야 합니다.

확인 위치

  • Xcode → Runner(프로젝트) → Runner(Target) → Build Settings

확인할 항목(대표)

  • Framework Search Paths$(inherited) 포함 여부
  • Other Linker Flags$(inherited) 포함 여부
  • Swift Compiler - Search Paths / Import Paths가 과도하게 커스텀되어 있지 않은지

많은 경우 “커스텀 스크립트/설정”이 $(inherited)를 덮어써서 Pods에서 내려준 경로가 사라집니다.


6) Apple Silicon(M1/M2) + 시뮬레이터/아카이브에서만 터지는 케이스

No such module Flutter가 특정 아키텍처에서만 발생한다면, 빌드 아키텍처 설정이 꼬였을 가능성이 있습니다.

점검

  • 시뮬레이터 빌드인지(arm64 simulator)
  • 아카이브 빌드인지(Release, device)

임시 회피(권장되진 않지만 진단용)

Podfile post_installEXCLUDED_ARCHS를 넣어 증상이 사라지는지 확인할 수 있습니다.

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
    end
  end
end

증상이 사라진다면 “아키텍처/바이너리 호환” 문제로 범위를 좁힐 수 있습니다. 다만 장기적으로는 플러그인/Pods가 arm64 simulator를 지원하도록 버전을 올리는 편이 낫습니다.


7) CI에서만 발생하는 경우: 캐시 전략과 순서가 핵심

CI에서 No such module Flutter가 뜨는 가장 흔한 원인은 다음입니다.

  • flutter pub get 이전에 pod install을 실행
  • ios/Flutter/Generated.xcconfig가 git에 없는데(정상) 생성도 안 함
  • 캐시된 Pods/ 또는 DerivedData가 다른 Flutter 버전 산출물을 물고 있음

CI 권장 순서(요약)

flutter --version
flutter clean
flutter pub get

cd ios
pod repo update
pod install
cd ..

flutter build ios --release

캐시를 쓴다면 Flutter SDK 버전, Podfile.lock, Xcode 버전을 키로 삼아 캐시를 분리하세요. 서로 다른 조합의 산출물을 섞으면 재현이 어려운 실패가 됩니다. 이런 류의 “환경 조합으로만 터지는 문제”는 원인-증상 매칭이 까다로운데, 네트워크/인프라 진단에서 타임아웃을 쪼개 추적하는 방식처럼 단계별로 격리하는 접근이 효과적입니다(예: Azure VM SSH 타임아웃 - NSG·UDR 진단 체크리스트).


8) 그래도 안 되면: 최소 재현으로 원인 좁히기

여기까지 했는데도 해결이 안 되면, “프로젝트 자체”가 아니라 “특정 플러그인/네이티브 코드 변경”이 트리거일 가능성이 큽니다.

권장 진단 루트

  1. 새 Flutter 프로젝트 생성 후 iOS 빌드가 되는지 확인
  2. 문제가 되는 프로젝트에서 ios/만 비교(특히 Podfile, Runner.xcodeproj 설정)
  3. 최근 추가한 플러그인/SDK를 하나씩 제거하며 재현 여부 확인

새 프로젝트는 되는데 기존만 안 된다면, ios/Runner.xcodeproj 내부 설정(빌드 설정 덮어쓰기, 스킴, 구성)이 손상되었을 수 있습니다.


결론: 가장 높은 확률의 해결 조합

실무에서 가장 자주 먹히는 “원샷 복구”는 아래 조합입니다.

  1. .xcworkspace로 열기
  2. flutter cleanflutter pub get
  3. pod deintegratepod install
  4. DerivedData 삭제

명령어로 정리하면 다음과 같습니다.

flutter clean
flutter pub get

cd ios
pod deintegrate
pod install
cd ..

rm -rf ~/Library/Developer/Xcode/DerivedData
open ios/Runner.xcworkspace

이후에도 재발한다면, Podfile 커스텀(use_frameworks! 등)과 Xcode Build Settings에서 $(inherited) 누락 여부를 최우선으로 의심하세요.

원하면, 에러 로그 전체(어느 파일에서 import Flutter가 실패하는지), Podfile, Flutter 버전/ Xcode 버전 정보를 주면 케이스를 더 좁혀서 “당장 필요한 최소 변경”만 제안할 수 있습니다.