Gu Doyoon

Expo Go + QR코드로 접속하면 ML Kit이 동작하지 않는 이유

3/7/2026 작성

npx expo start 후 QR코드로 Expo Go 앱에서 실행하면 ML Kit이 절대 동작하지 않는 경험을 저장하고자 작성합니다.


Expo Go란 무엇인가?

npx expo start를 실행하면 Metro 번들러가 JavaScript 코드를 번들링하고, QR코드를 통해 Expo Go라는 앱에 연결됩니다.

Expo Go는 Expo 팀이 미리 빌드해서 App Store / Play Store에 배포한 사전 컴파일된 앱입니다. 이 앱 안에는 자주 쓰는 Expo SDK 모듈들(카메라, 위치, 알림 등)이 이미 네이티브 코드로 내장되어 있습니다.


ML Kit은 왜 네이티브 코드가 필요한가?

Google ML Kit은 다음과 같은 구조로 동작합니다:

[JavaScript 코드] ↓ (React Native Bridge / JSI) [Native Module (Kotlin/Java or Swift/Obj-C)] [Google ML Kit SDK (네이티브 바이너리)] [On-device ML 추론 엔진]

ML 추론(이미지 인식, 텍스트 인식, 바코드 스캔 등)은 CPU/GPU에서 직접 실행되는 네이티브 코드입니다. JavaScript만으로는 절대 실행될 수 없습니다.


실제로 발생하는 에러 종류

1. NativeModule is null / Cannot read property of null

TypeError: null is not an object (evaluating 'RNMLKit.recognizeText')

JavaScript에서 네이티브 모듈을 호출했지만, Expo Go 내에 해당 모듈이 존재하지 않아 null을 반환합니다.

2. Invariant Violation: Native module not found

Invariant Violation: 'RNMLKitObjectDetection' native module not found.
Make sure the native module is properly linked.

"링크가 안 됐다"는 메시지가 뜨지만, 실제로는 Expo Go에 해당 모듈 자체가 존재하지 않는 것입니다.

3. Unable to resolve module

Unable to resolve module @react-native-ml-kit/text-recognition from ...

패키지는 설치했지만 Expo Go 런타임이 해당 네이티브 바인딩을 찾을 수 없을 때 발생합니다.

4. 앱 크래시 (즉시 종료)

모듈 초기화 시점에 네이티브 코드가 없으면 앱 자체가 강제 종료되는 경우도 있습니다.


왜 expo-camera 같은 건 되는데 ML Kit은 안 되나?

모듈Expo Go 포함 여부이유
expo-camera✅ 포함됨Expo SDK 공식 모듈
expo-image-picker✅ 포함됨Expo SDK 공식 모듈
expo-location✅ 포함됨Expo SDK 공식 모듈
react-native-mlkit-*❌ 미포함서드파티 네이티브 모듈
@react-native-ml-kit/*❌ 미포함서드파티 네이티브 모듈
react-native-vision-camera❌ 미포함서드파티 네이티브 모듈

Expo Go에는 Expo 공식 SDK 모듈만 사전 탑재되어 있습니다. 서드파티 네이티브 모듈은 빌드 시점에 직접 컴파일해야만 포함됩니다.


해결 방법: Development Build 사용

Expo Development Build는 내가 직접 빌드한 커스텀 Expo Go입니다. 서드파티 네이티브 모듈을 포함한 채로 빌드하므로 ML Kit이 정상 동작합니다.

방법 1: EAS Build (권장)

# 1. expo-dev-client 설치 npx expo install expo-dev-client # 2. EAS CLI 설치 및 로그인 npm install -g eas-cli eas login # 3. Development Build 빌드 eas build --profile development --platform android # 또는 eas build --profile development --platform ios # 4. 빌드된 앱 설치 후, 개발 서버 시작 npx expo start --dev-client

방법 2: 로컬 빌드 (Android)

# Android npx expo run:android # iOS (Mac 필요) npx expo run:ios

이 명령어는 android/ 또는 ios/ 폴더를 생성하고 네이티브 모듈을 포함한 앱을 로컬에서 빌드합니다.


프로젝트 적용 시 주의사항

app.json 플러그인 확인

{ "expo": { "plugins": [ "expo-router" // ML Kit 관련 config plugin이 있다면 여기에 추가 ] } }

expo prebuild가 ML Kit 패키지의 config plugin을 처리해야 Android build.gradle에 ML Kit 의존성이 추가됩니다.

Android build.gradle 의존성

ML Kit을 사용하려면 android/app/build.gradle에 다음이 자동으로 추가됩니다:

dependencies { implementation "com.google.mlkit:text-recognition:16.0.0" // 사용하는 ML Kit 모듈에 따라 상이 }

이 과정은 Development Build 시에만 실행됩니다. Expo Go에서는 이 단계가 없습니다.


정리

[npx expo start + Expo Go]
→ JS 번들만 교체 가능
→ 네이티브 모듈 추가 불가
→ ML Kit ❌

[Development Build / eas build]
→ 네이티브 모듈 포함하여 앱 컴파일
→ ML Kit ✅
→ On-device ML 추론 가능

Expo Go는 빠른 프로토타이핑을 위한 도구입니다. ML Kit처럼 네이티브 코드가 필요한 기능을 개발할 때는 처음부터 Development Build 환경을 구성하는 것이 맞습니다.


이 포스트는 safePedal 프로젝트에서 차대번호 인식을 위해 ML Kit을 도입하다 겪은 경험을 바탕으로 작성되었습니다.