【開発記 第2回】Android × Firebase × Gemini API で作る!AIアレルギー判定アプリの技術選定とシステム構成
一人でAIアプリをリリースするために。開発スピードと安全性を両立させた技術スタック
graph TD
subgraph "Client (Android App)"
A[Jetpack Compose UI] --> B[CameraX / OCR]
B --> C[Cloud Functions Call]
end
subgraph "Server (Google Cloud Platform)"
C --> D[Cloud Functions / Go]
D --> E[APP_INTERNAL_SECRET Check]
E --> F[Gemini API / AI Analysis]
D --> G[(Cloud Firestore)]
end
subgraph "External AI"
F --> H[Generative AI: Gemini 2.5 Flash]
end
G -.->|Cache Result| D
H -.->|Analysis Data| D
D -->|Safe / Caution / Danger| A1. セキュリティ:APIキーをアプリに持たせない
- 工夫点: Gemini APIキーをアプリ内に直接書き込まず、GCPのCloud Functionsを経由させる「プロキシ構成」を採用しました。
- メリット: 万が一アプリが解析(リバースエンジニアリング)されても、高額なAPI利用料が発生するキーが漏洩するリスクを最小限に抑えています。さらに、独自の合言葉(
APP_INTERNAL_SECRET)をヘッダーに含めることで、第三者からの不正なAPI呼び出しをブロックしています。
secret := os.Getenv("APP_INTERNAL_SECRET")
if r.Header.Get("X-App-Internal-Secret") != secret {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
2. 高速化:Firestoreによるキャッシュ戦略
- 工夫点: 一度誰かがスキャンした商品のJANコードとAIの判定結果は、Firestoreに保存するようにしました。
- メリット: 次に同じ商品を誰かがスキャンした際は、AIを動かさずにキャッシュから即座に回答を返せます。これにより「ユーザーの待ち時間短縮」と「APIコストの削減」を同時に実現しました。
3. 最新技術:Gemini 2.5 Flashの採用
- 工夫点: 判定モデルには、レスポンス速度とコストパフォーマンスに優れた「Gemini 2.5 Flash」を選択しました。
- メリット: 買い物中のユーザーを待たせない「爆速判定」を可能にしつつ、高度な文脈理解によって複雑な原材料名からリスクを正確に抽出しています。
「Glu-Suppo」を開発するにあたり、重視したのは**「スピード感」と「ユーザーの安心感」**の両立です。その結果、以下の技術スタックに辿り着きました。
技術選定の理由:なぜこのスタックなのか?
1. Kotlin & Jetpack Compose:宣言的UIが生む直感的な操作性
現代のAndroid開発において、Jetpack Composeを選択しない手はありません。
- 開発スピードの向上: 従来のXML形式に比べ、UIの構築が圧倒的に速く、コード量も大幅に削減できました。
- 動的な状態管理: 「判定中」「安全(緑)」「注意(オレンジ)」といった複雑なUIの状態遷移を、副作用(Side Effect)を抑えつつシンプルに記述できました。
- モダンな開発体験: Kotlinの強力な型推論とCoroutines(非同期処理)により、カメラ入力からAPI連携までをシームレスに記述できました。
2. Firebase:個人開発の強力なバックボーン
インフラの管理に時間をかけたくなかったため、Firebase(Google Cloud)をフル活用しました。
- Cloud Functions: APIキーを隠蔽するためのプロキシサーバーとして採用。サーバー管理(スケーリング)を自分で行う必要がないため、アプリ開発に集中できました。
- Cloud Firestore: 前述のキャッシュ戦略を実現するために使用。NoSQLのリレーショナルな構造は、JANコードと判定結果を紐づけて管理するのに最適でした。
3. Go言語:高速なサーバレス関数
サーバーレス環境でのコールドスタート(起動速度)を最小限に抑え、店頭でのレスポンスを1秒でも速くするため、バックエンドには私の得意な Go言語 を採用しました。
バックエンドの心臓部:Cloud Functions と Gemini API の連携
Glu-Suppoの「知能」は、どのように動いているのか。その連携フローを詳しく解説します。
セキュアな連携フロー
アプリから直接Gemini APIを叩くのではなく、以下のステップで連携を行っています。
- リクエストの検証: AndroidアプリからCloud Functionsへリクエストを送る際、独自ヘッダーに「秘密の合言葉(APP_INTERNAL_SECRET)」を含めます。サーバー側でこれを検証することで、不正な呼び出しをシャットアウトします。
- プロンプトエンジニアリング: Cloud Functions(Node.js)内で、原材料テキストをGeminiに渡す前に「判定ルール」を定義したプロンプトを付与します。「専門家として、科学的根拠に基づいて3段階で評価せよ」といった指示をサーバー側で制御することで、判定の精度と安定性を保っています。
- ストリーミング解析: Gemini 2.5 Flashの高速な推論結果をサーバー側で受け取り、JSON形式に整形してアプリへ返却します。
なぜGemini 2.5 Flashなのか?
このアプリにとって、スーパーの店頭での「待ち時間」は最大の敵です。 Gemini 2.5 Pro ほどの多機能さは必要なく、**「テキスト解析に特化した爆速のレスポンス」と「圧倒的な低コスト」**を誇るFlashモデルこそが、Glu-Suppoに最適な選択でした。
まとめ
「技術は、安心を支えるための裏方であるべき。」
今回ご紹介した「Android × Firebase × Gemini API」という構成は、個人開発としては少し贅沢に感じるかもしれません。しかし、ユーザーがスーパーの店頭でこのアプリを開いたとき、一瞬の迷いもなく「これは安全だ」と確信できる体験を作るためには、この強固で高速なインフラが必要不可欠でした。
複雑なセキュリティ対策も、Firestoreによるキャッシュ戦略も、すべては「買い物をもっと自由に、もっと楽しく」という目的のために存在しています。
さて、システムという「器」は整いました。しかし、このアプリの本当の心臓部は、その器の中で動く**「AIが、いかにして原材料名を正しく読み解き、安全性を判断しているか」**というロジックにあります。
次回、第3回では、私が最も試行錯誤を繰り返した**「AIプロンプト編」**をお届けします。 「蛋白加水分解物」や「醸造調味料」といった曖昧な表記に対して、Geminiにどのような指示(プロンプト)を与え、判定精度を極限まで高めていったのか。
その「AIへの教育」の裏側を詳しく解説します。どうぞお楽しみに!


ディスカッション
コメント一覧
まだ、コメントがありません