Gemma 3와 Flutter로 모바일에 엣지 서빙 및 성능 정리
대규모 언어 모델LLM은 점차 우리의 디지털 일상 깊숙이 자리 잡고 있지만, 클라우드에 의존해야 한다는 점은 여전히 활용의 걸림돌이 된다. 이동 중에도 AI를 제대로 활용하려면, 안정적인 인터넷 연결에 의존하지 않고 언제 어디서나 작동해야 한다.
이것이 바로 Google의 새로운 Gemma 3 모델 제품군이 해결하고자 설계된 문제다. Gemma 3는 프론티어급 모델[1]의 멀티모달 성능을 모바일과 포터블 디바이스에 탑재할 수 있는 수준으로 다가왔다는 점에서 눈여겨 볼 필요가 있다. 이 아티클에서는 Gemma 3를 모바일 디바이스에 구동하는 과정을 다루며 얻었던 인사이트와 결과를 공유하기 위해 작성되었다. 10억 파라미터 Gemma 3 모델을 iPhone에서 실행되는 Flutter 채팅 앱을 만드는 과정을 단계별로 안내하며, 구현 과정에서의 기술적 문제와 해결책을 공유한다.
전체 소스 코드는 아래 GitHub 리포지토리에서 확인할 수 있다.
KennethanCeyer/gemma3-chat-app
A sample Flutter application for Gemma3 Edge-serving
요약 (TL;DR)
- Gemma 3 모바일 지원: Flutter와 MediaPipe GenAI 패키지를 사용하여 iOS에서 Gemma 3 (1B) 모델을 온디바이스로 실행할 수 있다.
- 아직 실험적인 단계: 빌드를 위해 Flutter의 마스터 채널을 사용하여 실험적인 기능을 활성화해야 한다.
- 의존성 연결 필요: 표준 빌드 프로세스가 네이티브 MediaPipe 종속성(MediaPipeTasksGenAI, MediaPipeTasksGenAIC)을 자동으로 처리하지 않으므로, 이를 올바르게 연결하려면 수동으로 생성된 이 현재 필요하다.
- 모델 적재 필요: 네이티브 코드가 모델에 접근할 수 있으려면, 첫 실행 시 Flutter의 에셋에서 앱의 로컬 디바이스 저장소로 모델을 복사해야 한다.
왜 온디바이스에 Gemma 3를 사용하나

이번 엣지 서빙 과정에서 Gemma 3를 선택한 것은 다음과 같은 이유 때문이었다.
- Google의 오픈 가중치 모델[2]이며, Gemini 모델과 동일한 연구를 기반으로 하지만 엣지 디바이스에서의 효율성을 위해 특별히 설계되었다. 그 아키텍처는 데이터 센터에 갇혀 있던 최신 AI 기술을 사용자의 손안에서 직접 구동할 수 있도록 설계되었다.
- 형식 자체가 큰 편의성을 제공한다. 이는 핵심 TensorFlow Lite[5] 모델, 토크나이저 및 기타 메타데이터를 단일 파일로 패키징하는 MediaPipe 모델 번들로, 배포 과정을 단순화한다.

Gemma 3는 1B, 4B, 12B, 27B 등 다양한 크기의 모델로 제공되어 사용 목적과 환경에 맞춰 선택할 수 있다. 4B 이상의 모델은 멀티모달 입력을 지원하는 반면, 1B 모델은 텍스트 전용으로 설계되어 모바일 기기에서의 효율성을 극대화했다. 이번 프로젝트에서는 모바일 환경에 최적화된 Gemma 3 1B IT[6] 버전을 사용했다.
벤치마크
다음은 Gemma 3 1B 모델의 주요 벤치마크 성능이다. 동시기에 출시된 경량형 모델들과 비교했을 때, 특히 상식 추론 영역에서 준수한 성능을 보여준다.
| Benchmark | Metric | Gemma 3 PT 1B | 비고 |
|---|---|---|---|
| HellaSwag | 10-shot | 62.3 | 상식 추론[7] |
| BoolQ | 0-shot | 63.2 | 예/아니오 질의응답[8] |
| PIQA | 0-shot | 73.8 | 물리적 상식[9] |
| SocialIQA | 0-shot | 48.9 | 사회적 상식[10] |
| TriviaQA | 5-shot | 39.8 | 일반 상식[11] |
| Natural Questions | 5-shot | 9.48 | 질의응답[12] |
| ARC-c | 25-shot | 38.4 | 과학적 추론Challenge[13] |
| ARC-e | 0-shot | 73.0 | 과학적 추론Easy[14] |
| WinoGrande | 5-shot | 58.2 | 상식 추론 (대명사)[15] |
| BIG-Bench Hard | few-shot | 28.4 | 종합적 난제[16] |
| DROP | 1-shot | 42.4 | 독해 및 산술[17] |
Gemma 3 1B는 비슷한 시기에 출시된 Llama 3.2 1B 등의 경쟁 모델과 비교했을 때, PIQA(물리적 상식)와 ARC-e(기초 과학) 등에서 강점을 보인다. 특히 모바일 디바이스에서 구동 가능한 10억 파라미터 사이즈임에도 불구하고, 32K 컨텍스트 윈도우[18]를 지원하여 긴 문맥을 이해해야 하는 작업에서 유리한 고지를 점하고 있다.
모델 구조
| Parameter | Value |
|---|---|
| Embedding Size ()[19] | 1,152 |
| Layers[20] | 26 |
| Feedforward Hidden Dims | 13,824 |
| Num Heads[21] | 4 |
| Num Key Value Heads[22] | 1 |
| Query Key Value Head Size | 256 |
| Vocab Size (SentencePiece)[23] | 262,144 |
| Context Window | 32k |
이 1B 모델은 26개의 레이어와 1,152의 임베딩 사이즈를 갖추고 있어 모바일 환경에서도 깊이 있는 언어 이해가 가능하다. 특히 32k의 컨텍스트 윈도우는 긴 대화나 문서를 처리하는 데 있어 큰 이점을 제공하며, 26만 개 이상의 방대한 어휘 사전은 다국어 처리 능력을 뒷받침한다. 4개의 헤드와 1개의 KV 헤드를 사용하는 구조는 메모리 대역폭을 효율적으로 사용하여 빠른 추론 속도에 기여한다.
왜 크로스플랫폼 AI 앱에 Flutter를 사용할까?

모델을 선택한 후, 다음 결정은 애플리케이션 프레임워크였다. Flutter는 두 가지 주요 이유로 이 프로젝트에 적합한 선택이었다.
- 고품질 네이티브 경험: Flutter는 단일 코드베이스로 iOS와 Android 모두를 위한 고성능, 네이티브 컴파일 애플리케이션을 구축할 수 있게 해준다. 이는 UI가 빠르고 반응성이 좋으며, 해당 플랫폼에서 자연스럽게 느껴진다는 것을 의미한다.
- 뛰어난 네이티브 상호 운용성: 기술적으로 눈여겨볼 부분은 Flutter의 FFI[24] 기능이다. 이를 통해 Dart 코드가 Gemma 모델을 실행하는 네이티브 C++ MediaPipe 라이브러리를 원활하게 호출할 수 있다. 이 직접적인 통신 라인은 모델에 프롬프트를 전달하고 응답 스트림을 효율적으로 수신하는 데 필요하다.
Flutter와 Gemma를 연결하는 다리는 MediaPipe[25]다. 특히 이 프로젝트에서는 mediapipe_genai 패키지를 사용하여 LLM 추론을 구현했다. MediaPipe에 대한 더 자세한 정보와 사용법은 공식 가이드에서 확인할 수 있다. 이는 모델을 관리하고 추론 작업을 실행하는 저수준의 복잡성을 처리한다.
구현: 단계별 가이드
이 최첨단 스택을 작동시키려면 특정 환경과 몇 가지 수동 해결 방법이 필요했다.
1. 환경: 마스터 채널
mediapipe_genai 패키지는 새롭고 실험적인 native-assets 기능에 의존한다. 기본적으로 Dart 패키지가 네이티브 라이브러리(C/C++, Rust 등)를 손쉽게 번들링하고 사용할 수 있도록 돕는 기능이지만, 아직 안정 채널에 포함되지 않았으므로 프로젝트를 Flutter 마스터 채널을 사용하도록 구성해야 한다.
2. 네이티브 링킹 문제 (iOS Podfile)

가장 큰 어려움은 네이티브 링킹 오류(symbol not found)였다. Flutter 빌드 도구가 MediaPipe 라이브러리를 최종 iOS 앱에 자동으로 연결하지 못했다.
해결책은 필요한 네이티브 종속성을 선언하기 위해 ios/Podfile을 수동으로 만드는 것이었다. 이 단계는 빌드 도구가 라이브러리를 자동으로 연결하지 않았기 때문에 필요했으며, CocoaPods가 MediaPipe 라이브러리를 최종 앱에 올바르게 통합하도록 보장한다.
ios/Podfile:
이 파일을 만든 후, ios 디렉토리에서 pod install을 실행해야 한다.
3. Dart 코드 (main.dart)
애플리케이션 로직은 에셋에서 모델을 로드하고 추론을 실행하는 것을 처리한다. 핵심 단계는 큰 모델 파일을 로컬 디렉토리로 복사하여 네이티브 코드가 직접 접근할 수 있도록 하는 것이다.
엔진 초기화:
응답 생성: 실시간 타이핑 효과를 얻기 위해, generateResponse가 반환하는 Stream을 수신하고 각 텍스트 청크로 UI를 업데이트한다.
결론
이번 실험을 통해 iOS 환경에서 Flutter와 MediaPipe를 조합하여 Gemma 3 1B 모델을 구동하는 것이 가능하다는 것을 확인했다. 특히 최신 iPhone 모델에 탑재된 NPUNeural Processing Unit, Apple Neural Engine를 활용하면 일반적으로 사용 가능한 수준의 토큰 생성 속도를 기대할 수 있다. 다만 메모리 제약과 이로 인한 NPU 로딩이 아닌 CPU 로딩으로 인한 성능 저하 문제, 배터리 사용량과 발열량, 그리고 스로틀링으로 인한 성능 저하 문제가 발생할 수 있다.
필자가 테스트에 사용한 iPhone 13 Pro는 A15 Bionic 칩셋을 탑재하고 있으며, 여기에는 초당 15조 8천억 회(15.8 TOPS)의 연산을 수행할 수 있는 16코어 Neural Engine이 내장되어 있다. Apple은 A11 Bionic부터 NPU를 탑재하기 시작했으며, 이 하드웨어 가속기는 Metal 가속 시스템을 통해 활용된다. 즉, 소프트웨어적으로는 Metal 백엔드를 사용하지만, 실제 무거운 행렬 연산은 이 NPU가 담당하여 약 20~40 토큰/초의 성능을 낼 수 있게 되는 것이다. Neural Engine에 대한 자세한 스펙과 트랜스포머 아키텍처 최적화에 대한 내용은 Apple의 Machine Learning Research에서 확인할 수 있듯이, Apple Neural EngineANE[26]는 트랜스포머 모델의 추론 워크로드를 효율적으로 처리하여 앱의 메모리 영향과 배터리 소모를 최소화하도록 설계되었다.
하지만 실제 온디바이스 배포 시에는 몇 가지 주의사항이 있다.
- 메모리 제약: 1B 모델이라 하더라도 양자화Quantization[27]되지 않은 상태거나 텍스트 컨텍스트가 길어질 경우, 아이폰의 통합 메모리Unified Memory 한계에 도달할 수 있다. 특히 6GB 램을 탑재한 구형 모델에서는 앱이 강제 종료될 위험이 있다.
- 발열과 스로틀링: NPU와 GPU를 풀로드로 사용하면 기기 발열이 급격히 상승한다. iOS는 기기 보호를 위해 성능을 제한하는 스로틀링Throttling을 걸게 되는데, 이 경우 추론 속도가 급격히 저하될 수 있다.
- CPU 폴백: 특정 연산자Operator가 Metal 셰이더로 최적화되지 않았거나 메모리가 부족한 경우, MediaPipe는 자동으로 CPU 모드로 전환될 수 있다. 이 경우 성능은 1/10 수준으로 떨어질 수 있어, 프로파일링을 통한 확인이 필요하다.
그럼에도 불구하고 32K 컨텍스트 윈도우를 지원하는 1B 모델을 오프라인 모바일 환경에서 구동할 수 있다는 점은, 개인 정보 보호가 중요한 온디바이스 AI 애플리케이션 개발에 있어 매우 매력적인 선택지가 될 것이다. 현시점에서는 실험적인 기능(native-assets)과 수동 설정이 필요하지만, 도구 모음Toolchain이 성숙해짐에 따라 더욱 쉬운 통합이 가능해질 것으로 기대된다.
각주
- 1: 인공지능 분야의 최전선에 있는 최고 성능의 모델들을 일컫는 말 [↩︎]
- 2: 모델의 가중치(파라미터)와 구조는 공개되었으나, 학습 데이터셋과 전체 훈련 과정은 완전히 공개되지 않은 모델 [↩︎]
- 3: 1 Billion, 10억 개의 파라미터를 의미 [↩︎]
- 4: 4-bit Integer Quantization, 모델의 크기를 줄이기 위한 4비트 정수 양자화 기법 [↩︎]
- 5: 구글의 온디바이스 추론을 위한 경량 머신러닝 프레임워크 [↩︎]
- 6: Instruct Tuned, 사용자의 지시를 따르도록 미세 조정Fine-tuning된 모델로, 채팅 및 질의응답에 적합함 [↩︎]
- 7: 문장의 문맥을 이해하고 가장 알맞은 결말을 예측하는 능력을 평가 [↩︎]
- 8: 주어진 단락을 읽고 예/아니오로 대답할 수 있는 질문에 답하는 능력을 평가 [↩︎]
- 9: 일상적인 물리적 상황에 대한 상식적인 해결책을 선택하는 능력을 평가 [↩︎]
- 10: 사회적 상황에서의 사람들의 행동과 그 이유를 추론하는 능력을 평가 [↩︎]
- 11: 다양한 주제에 대한 사실적 지식을 묻는 질문에 답하는 능력을 평가 [↩︎]
- 12: 실제 구글 검색 쿼리를 바탕으로 위키피디아 문서에서 정답을 찾는 능력을 평가 [↩︎]
- 13: 초등학교/중학교 수준의 과학 문제 중 검색만으로는 풀기 어려운 문제들을 평가 [↩︎]
- 14: 초등학교/중학교 수준의 과학 문제 중 비교적 쉬운 문제들을 평가 [↩︎]
- 15: 문맥에 따라 모호한 대명사가 무엇을 지칭하는지 파악하는 능력을 평가 [↩︎]
- 16: 현재 언어 모델들이 어려워하는 다양한 난이도의 작업들을 모아놓은 벤치마크 [↩︎]
- 17: 텍스트를 읽고 그 안에 포함된 정보를 바탕으로 산술적인 연산을 수행해야 하는 능력을 평가 [↩︎]
- 18: 한 번에 처리할 수 있는 토큰의 양. 32K는 약 24,000 단어 정도의 긴 문서를 한 번에 입력받을 수 있음을 의미 [↩︎]
- 19: 단어를 고차원 벡터로 변환하는 레이어의 크기로, 모델이 표현할 수 있는 의미의 복잡도를 결정 [↩︎]
- 20: 모델의 깊이를 나타내며, 추론 능력과 복잡한 패턴 학습 능력에 영향을 줌 [↩︎]
- 21: 어텐션 메커니즘을 병렬로 수행하는 헤드의 수로, 다양한 관점에서 정보를 처리하게 함 [↩︎]
- 22: GQAGrouped Query Attention 등이 적용된 경우 쿼리 헤드 수보다 적을 수 있으며, 메모리 효율성을 높임 [↩︎]
- 23: Google에서 개발한 비지도 텍스트 토크나이저 및 디토크나이저 [↩︎]
- 24: Foreign Function Interface, 다른 언어로 작성된 함수를 호출하기 위한 인터페이스 [↩︎]
- 25: 구글이 제공하는 온디바이스 머신러닝 솔루션으로, 비전, 텍스트, 오디오 등 다양한 모달리티를 지원 [↩︎]
- 26: Apple 실리콘 칩에 내장된 NPU로, 머신러닝 작업에 최적화된 하드웨어 가속기 [↩︎]
- 27: 모델의 파라미터 정밀도를 낮춰(예: 32-bit float -> 4-bit integer) 메모리 사용량과 연산 비용을 줄이는 최적화 기법 [↩︎]
추천 아티클
GPU는 어떻게 머신러닝 연산을 수행할까?
Python 코드 한 줄이 GPU의 트랜지스터를 움직이기까지의 JAX와 CUDA를 통해 보는 하드웨어 가속의 원리를 탐구해보자.
JAX와 TPU를 이용한 Decoder-based Tiny LLM 사전학습
JAX와 Cloud TPU v6e를 활용하여 Llama 스타일의 Tiny LLM을 바닥부터 구현하고 사전 학습하는 과정을 다룬다. RMSNorm, SwiGLU, RoPE 등 최신 아키텍처와 고성능 I/O 파이프라인 구축 방법을 알아본다.