방법

지능형 Android 앱 빌드: 클라우드 및 하이브리드 추론

전문 길이: 8분

기본 Android 앱을 맞춤설정되고 지능적이며 에이전트적인 환경으로 변환하는 블로그 게시물 시리즈 '지능형 Android 앱 빌드'에 다시 오신 것을 환영합니다. 이전 게시물에서는 ML Kit의 프롬프트 API를 통해 Gemini Nano를 사용하여 지능형 기기 내 기능을 빌드하는 방법을 살펴봤습니다.

이 게시물에서는 Firebase AI Logic 을 활용하여 클라우드 호스팅 및 하이브리드 AI 기능을 빌드하는 방법을 알아봅니다. 

  • 실제 상황에 기반한 대답
  • 하이브리드 추론을 사용하여 클라우드와 로컬 실행 간에 요청을 동적으로 라우팅
  • 맞춤 라우팅 시스템으로 콘텐츠 번역

경우에 따라 사용 사례에 전 세계 지식이 더 풍부하고, 컨텍스트 윈도우가 훨씬 크며, 복잡한 질문을 처리할 수 있는 AI 모델이 필요합니다. 이러한 시나리오에서는 클라우드 모델을 활용할 수 있습니다. 

때로는 하이브리드 추론을 사용하여 비용을 절감하기 위해 온디바이스에서 실행하고 모든 기기의 호환성을 보장하기 위해 클라우드로 대체하는 등 두 가지 기능의 장점을 모두 누리고 싶을 수도 있습니다.

features.png
Jetpacker의 클라우드 및 하이브리드 기능: 웹 그라운딩을 사용하는 박물관 도우미, 하이브리드 레스토랑 리뷰 초안 작성, 맞춤 라우팅 실시간 번역을 지원하는 채팅

Jetpacker에서 세 가지 클라우드 및 하이브리드 기능을 구현한 방법을 살펴보겠습니다.

  • 웹 그라운딩을 갖춘 박물관 어시스턴트
  • 하이브리드 음식점 리뷰 초안 작성
  • 맞춤 라우팅된 실시간 번역을 제공하는 호텔 지원 채팅

LLM 그라운딩을 사용하여 최신 정보 제공박물관 도우미 챗봇(LLM 그라운딩 사용)

박물관 어시스턴트 는 사용자가 박물관 방문을 계획할 수 있도록 설계된 대화형 챗봇입니다. 방문자에게 특정 전시물, 현재 영업시간, 티켓 가격 등에 관한 최신 세부정보를 제공합니다.

museum_assistant_upscaled.png
박물관 어시스턴트는 '루브르 박물관 티켓 할인을 받으려면 어떻게 해야 하나요?'과 같은 질문에 답하는 챗봇입니다.

AI 기능을 빌드할 때 모델이 최신 정보, 정확한 정보, 구체적인 실제 정보를 사용하여 답변하도록 하는 것은 일반적인 과제입니다. 클라우드 모델은 방대한 양의 세상 지식을 보유하고 있지만, 시즌별 전시나 당일 영업시간에 대해서는 알지 못할 수 있습니다.

grounding.png
모델이 질문에 올바르고 정확하게 답변할 수 있도록 그라운딩 데이터가 컨텍스트 윈도우에 추가됩니다.

이 격차를 해소하기 위해 그라운딩 기법을 사용하여 모델의 컨텍스트 윈도우에 추가 컨텍스트를 추가할 수 있습니다. Firebase AI Logic SDK는 다음과 같은 세 가지 유형의 그라운딩을 지원합니다.

  • URL 그라운딩: 특정 웹페이지의 콘텐츠 (예: 현재 티켓 가격 또는 박물관 규칙)를 사용하여 대답을 그라운딩합니다.
  • Google 검색 그라운딩: 모델이 최신 세부정보를 위해 실시간 Google 검색 색인에 쿼리하도록 허용합니다.
  • 지도 그라운딩: Google 지도 위치 데이터를 사용합니다.

Jetpacker에서는 사용 설정된 기능 플래그를 기반으로 사용 가능한 도구를 동적으로 구성하고 Firebase AI SDK를 사용하여 생성형 모델을 초기화합니다.

// implementation("com.google.firebase:firebase-ai-logic")

private var toolList = mutableListOf<Tool>()

init {
    if (ENABLE_SEARCH_GROUNDING) {
        toolList.add(Tool.googleSearch())
    }
    if (ENABLE_URL_GROUNDING) {
        toolList.add(Tool.urlContext())
    }
}

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        systemInstruction = content {
            text("You are a helpful museum assistant answering questions about a museum. Use plain text.")
        },
        tools = toolList
    )

사용자가 어시스턴트에 질문할 때 URL 그라운딩이 사용 설정되어 있으면 특정 박물관 리소스 URL이 프롬프트에 직접 추가됩니다.

val groundingText = if (FeatureFlags.ENABLE_URL_GROUNDING) {
    "\n If the following message above is about the rules and terms to visit Le Louvre, " +
    "if needed answer this urls ${urlList.joinToString()}"
} else {
    ""
}

val prompt = "$text $groundingText"

var response = chat.sendMessage(prompt)

모든 AI 태스크에 클라우드 기반 모델이 필요한 것은 아니며 모든 기기가 온라인 상태인 것도 아닙니다. 개발자가 지연 시간, 비용, 오프라인 사용 가능 여부의 균형을 맞출 수 있도록 최근 하이브리드 추론을 위한 Firebase API가 도입되었습니다.

Jetpacker에서 음식점 리뷰 기능을 사용하면 사용자가 특정 주제를 검토하고 리뷰를 자동으로 작성할 수 있습니다. 모든 사용자를 위해 이 기능을 사용 설정하기 위해 Google은 Gemini Nano를 사용한 로컬 실행을 우선시하고 Gemini Nano를 지원하지 않는 기기에서는 클라우드 모델로 대체합니다. 

review_upscaled.png
식당 리뷰 기능은 하이브리드 추론을 사용하여 주제에 따라 리뷰를 작성합니다
// implementation("com.google.firebase:firebase-ai-logic")
// implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta03")


// Initialize the model with hybrid routing configuration
val reviewModel = Firebase.ai.generativeModel(
    modelName = "gemini-3.1-flash-lite",
    onDeviceConfig = OnDeviceConfig(
        inferenceMode = InferenceMode.PREFER_ON_DEVICE
    )
)

Hybrid Inference API는 다음과 같은 네 가지 라우팅 모드를 지원합니다.

  • PREFER_ON_DEVICE: 로컬 실행을 우선시하고 Gemini Nano를 사용할 수 없는 경우 클라우드로 대체합니다.
  • PREFER_IN_CLOUD: 클라우드 실행을 우선시하고 기기가 오프라인 상태가 되면 온디바이스로 대체합니다.
  • ONLY_ON_DEVICE: 실행을 기기로만 엄격하게 제한합니다.
  • ONLY_IN_CLOUD: 실행을 클라우드로만 엄격하게 제한합니다.

리뷰가 생성되면 클립보드에 복사하고 인텐트를 사용하여 Google 지도를 식당의 리뷰 페이지로 직접 열어 원활한 사용자 환경을 제공합니다.

private fun copyAndOpenMapsReview(context: Context, reviewText: String, placeId: String) {
    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("User Review", reviewText)
    clipboard.setPrimaryClip(clip)

    val uri = Uri.parse("https://search.google.com/local/writereview/mobile?placeid=$placeId")
    val intent = Intent(Intent.ACTION_VIEW, uri).apply {
        setPackage("com.google.android.apps.maps")
    }
    context.startActivity(intent)
}

맞춤 하이브리드 라우팅: 시뮬레이션된 페르소나를 사용한 호텔 지원 채팅 번역

호텔 지원 채팅은 사용자가 물류를 마무리하고 호텔 세부정보를 확인할 수 있도록 설계되었습니다. 이 기능은 시스템 안내를 사용하여 현지화된 리셉션 도우미를 구성합니다. 요청 사항에 기본 언어, 호텔 정보와 같은 특정 정보를 전달하면 특정 호텔을 나타내는 대화형 페르소나를 설정할 수 있습니다.

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        systemInstruction = content {
            text("""
              You are a helpful hotel receptionist at $hotelName only speaking $language. 
              Answer politely in $language. The bar closes at 10pm and breakfast is from 7am to 10am.
              There's someone at the desk 24/7. You can retrieve your luggage from the storage room 
              at the back of the lobby at any time.
              """)
        },
        modelName = "gemini-3-flash-preview"
    )

리셉션 응답은 호텔의 현지 언어 (예: 파리의 Hotel Le Meurice의 경우 프랑스어)로 제공되므로 메시지를 사용자가 선호하는 언어로 번역해야 합니다.

translation_upscaled.png
호텔 지원 채팅 메시지가 사용자가 선호하는 언어로 자동 번역됩니다. 

하이브리드 모델은 간단한 라우팅 환경설정을 구성할 수 있지만 복잡한 시나리오에는 맞춤 라우팅 로직이 필요합니다. Jetpacker에서는 다음을 고려하는 맞춤 라우팅 스택을 구현합니다.

  • 언어 식별: 기기 내 ML Kit 언어 식별 API를 사용하여 받은 메시지 언어를 감지할 수 있습니다.
  • 온디바이스 번역 (Gemini Nano): ML Kit의 프롬프트 API를 사용하면 기기에서 직접 일반적인 언어 쌍을 번역하여 대역폭과 클라우드 비용을 절약할 수 있습니다.
  • 클라우드 번역 (Gemini 3 Flash): 더 복잡한 언어의 경우 Gemini Flash 3를 사용하여 더 높은 품질의 번역을 제공합니다.
// implementation("com.google.android.gms:play-services-mlkit-language-id:17.0.0") 

// ML Kit for Language Identification (powered by Google Play Services)
private val languageIdentifier = LanguageIdentification.getClient()

// On-device translator model (prefer Gemini Nano) for translating common language pairs
private val hybridTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.PREFER_ON_DEVICE)
    )

// Cloud translator model for more complex language pairs
private val cloudTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash"
    )

메시지를 번역해야 하는 경우 Google에서는 출발어를 식별하고 맞춤 라우팅 로직을 적용하여 온디바이스 또는 클라우드 번역을 실행합니다.

fun translateMessage(message: SupportChatMessage) {
    viewModelScope.launch {
        // 1. Detect language using ML Kit Language Identification
        val sourceLang = try {
            Tasks.await(languageIdentifier.identifyLanguage(message.text))
        } catch (e: Exception) {
            "Undefined"
        }

        // 2. Custom routing: we've verified the translation quality for English and Korean with Gemini Nano, and will translate message on-device for those two languages
        val routeToCloud = sourceLang != "en" && sourceLang != "kr"

        val prompt = "Translate the following text to $selectedLanguage. Just return the translated sentence: ${message.text}."

        val (translatedText, routePrefix) = if (routeToCloud) {
            val result = cloudTranslationModel.generateContent(prompt)
            result.text to "[Cloud]"
        } else {
            val result = hybridTranslationModel.generateContent(prompt)
            result.text to "[On-Device]"
        }

        if (translatedText != null) {
            _translations.update { current ->
                current + (message.id to "$routePrefix: $translatedText")
            }
        }
    }
}

이 예시에서 맞춤 라우팅 로직은 번역의 소스 언어와 대상 언어만 고려합니다. 하지만 앱의 사용 사례에 따라 라우팅 로직을 확장하여 온디바이스 모델 버전, 네트워크 연결, 배터리 상태 등의 다른 요소를 포함할 수 있습니다.

AI 파이프라인 보안: Firebase 앱 체크

마지막으로 클라우드에서 AI를 사용하면 API 키 남용 또는 승인되지 않은 청구의 가능성이 열립니다. API 호출을 보호하기 위해 Play Integrity (프로덕션)와 로컬 디버그 제공자 (로컬 개발 또는 에뮬레이터용)를 모두 사용하여 Firebase 앱 체크를 통합했습니다.

JetPackerApplication.kt 파일에서 시작 시 디버그 제공자를 설치하고 익명 인증을 트리거하여 보안 사용자 세션을 설정합니다.

//  implementation("com.google.firebase:firebase-appcheck-playintegrity") 
//  implementation("com.google.firebase:firebase-appcheck-debug")  
//  implementation("com.google.firebase:firebase-auth") 

override fun onCreate() {
    super.onCreate()
    Firebase.initialize(context = this)
    Firebase.appCheck.installAppCheckProviderFactory(
        DebugAppCheckProviderFactory.getInstance()
    )
    Firebase.auth.signInAnonymously()
}

에뮬레이터에서 로컬로 빌드할 때 App Check는 logcat에 로컬 토큰 보안 비밀을 출력합니다.

Enter this debug secret into the allow list in the Firebase Console: a8c2dd4c-xxxx-xxxx-xxxx-ef6c114ba27e

Firebase Console에 등록되면 로컬 요청이 앱 체크에 의해 완전히 검증되고 인증되어 백엔드를 보호하면서 앱을 로컬로 테스트할 수 있습니다.

결론

클라우드 모델 기능 (그라운딩, 시스템 명령어)과 온디바이스 기능 (하이브리드 라우팅, 번역, 보안 앱 확인)을 결합하여 오프라인에서 사용할 수 있는 스마트하고 안전한 여행 앱을 만들었습니다.

GitHub에서 Jetpacker의 전체 소스 코드를 확인하고 Firebase 문서를 살펴보고 시작하세요.

Firebase AI Logic 문서
Firebase 하이브리드 추론 API

자세히 알아보기

이 블로그 게시물 시리즈의 다른 부분을 확인하세요.

1부: 앱 소개 및 개요.
2부: 온디바이스 인텔리전스 ML Kit의 생성형 AI API와 Gemini Nano를 자세히 살펴보고 여행 일정 요약, 영수증 파싱, 로컬 오디오 처리와 같은 개인 정보 보호 우선 기능을 빌드하세요.
3부 (이 게시물): 하이브리드 및 클라우드 추론 Firebase AI Logic을 사용하여 Google 지도 및 웹 컨텍스트와 같은 실제 데이터를 기반으로 LLM 답변을 제공하는 방법을 알아봅니다.
4부: 시스템 통합 AppFunctions를 사용하여 Android 인텔리전스 시스템과 통합 
파트 5 (출시 예정): 인앱 에이전트 워크플로 A2UI 및 ADK로 구동되는 엔드 투 엔드 예약 어시스턴트로 앱을 확장합니다.

Android 개발에 대해 자세히 알아보고 싶으신가요? YouTube 또는 LinkedIn에서 Android 개발자를 팔로우하세요.

이 블로그 게시물의 모든 코드 스니펫에는 다음 저작권 고지가 적용됩니다.

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0
작성자:
계속 읽기