KORTRESS
2026-09-26• ai

안드로이드 App Functions 심층 분석: 온디바이스 AI 에이전트를 위한 모바일 MCP

by Ko

들어가는 말: 모바일 앱과 AI 에이전트의 접점 변화

스마트폰의 AI 비서(Google Assistant, Siri 등)는 오랫동안 '정해진 인텐트(Intent)'와 '정적 딥링크'에 갇혀 있었습니다. 사용자가 "음악 틀어줘"라고 말하면 시스템은 사전에 하드코딩된 액션을 매핑하여 앱을 포그라운드로 띄우는 것이 고작이었습니다.

하지만 온디바이스 거대 언어 모델(Gemini Nano 등)과 자율 에이전트가 OS 레벨에 통합되면서 모바일 앱과의 상호작용 방식이 근본적으로 변하고 있습니다. 에이전트는 사용자의 자연어 명령을 해석해 적절한 도구(Tool)를 직접 선택하고, 매개변수를 생성하여 백그라운드에서 실행할 수 있어야 합니다.

구글은 Android 16(API Level 36)과 신규 Jetpack 라이브러리인 **androidx.appfunctions**를 통해 이를 시스템 표준으로 정립했습니다. 데스크톱 개발 환경에 Anthropic의 **MCP(Model Context Protocol)**가 있다면, 안드로이드 모바일 생태계에는 App Functions가 그 역할을 수행합니다.


1. 안드로이드 상호작용 프레임워크의 진화 계보

안드로이드에서 앱의 기능을 외부 시스템에 개방하던 방식은 다음과 같은 단계를 거쳐 발전했습니다.

세대기술 명칭연동 방식한계점
1세대Android Shortcuts정적/동적 딥링크 (Deep Link)런처 롱프레스나 단순 URL 라우팅에 불과, AI가 파라미터를 추론하여 함수를 호출 불가
2세대App Actions & Slices구글 어시스턴트 Built-in Intent(BII) 매핑구글이 정의한 수십 개의 고정 스키마 외에는 커스텀 확장이 어렵고, UI 렌더링(Slices) 유지보수 부담 큼
3세대App Functions<br>(androidx.appfunctions)온디바이스 AI 에이전트 전용 타입세이프 Function Calling앱을 직접 띄우지 않고 백그라운드에서 메서드 실행, KDoc 기반 자동 스키마 생성, 완전한 커스텀 도구 정의 지원

과거의 App Actions가 구글 어시스턴트를 위한 "미리 정해진 문장-인텐트 매핑표"였다면, App Functions는 LLM의 Function Calling(Tool Use)을 온디바이스에서 안전하게 실행하기 위한 표준 IPC(Inter-Process Communication) 규약입니다.


2. 아키텍처 개요: 앱이 '온디바이스 MCP 서버'가 되는 구조

[ 사용자 자연어 입력 ]
"내일 오후 3시에 팀 미팅 일정 등록하고 슬랙 알림 맞춰줘"
                      │
                      ▼
[ 시스템 AI 에이전트 (Gemini / OS Agent) ]
                      │ 1. 등록된 App Functions 스키마 조회 (Tool Discovery)
                      │ 2. 필요한 함수 및 인자 결정 (Function Calling)
                      ▼
[ Android AppFunctionManager (시스템 서비스) ]
                      │ 3. 권한 검증 (EXECUTE_APP_FUNCTIONS)
                      │ 4. 샌드박스 바인더 호출
                      ▼
[ 서드파티 앱 : AppFunctionService ]
                      │ 5. @AppFunction 어노테이션 메서드 실행
                      ▼
[ 결과 반환 (JSON / Serializable Data) ] ➔ AI 에이전트가 다음 행동 수행

App Functions 아키텍처는 크게 세 가지 구성 요소로 나뉩니다:

  1. 에이전트 (Caller / Client): 시스템 권한을 가진 AI 에이전트(예: Gemini 앱, 시스템 어시스턴트)가 사용자의 발화를 분석하고 호출할 함수와 매개변수를 결정합니다.
  2. 시스템 브로커 (AppFunctionManager): 안드로이드 OS 플랫폼 서비스로, 호출자의 권한을 검증하고 서드파티 앱의 백그라운드 서비스를 바인딩하여 안전하게 실행을 중계합니다.
  3. 앱 구현체 (AppFunctionService): 서드파티 개발자가 @AppFunction으로 선언한 비즈니스 로직 단위입니다.

3. 핵심 구성 요소 및 빌드 파이프라인

androidx.appfunctions 라이브러리는 다음 아티팩트들로 구성됩니다.

  • androidx.appfunctions:appfunctions: 런타임 코어 인터페이스
  • androidx.appfunctions:appfunctions-service: 기능을 제공하는 앱 서비스 구현체
  • androidx.appfunctions:appfunctions-compiler: KSP(Kotlin Symbol Processing) 컴파일러 (스키마 자동 생성)
  • androidx.appfunctions:appfunctions-testing: 유닛 및 통합 테스트 도구

KDoc 주석의 결정적 역할

LLM이 API를 호출할 때 가장 중요한 것은 "이 함수가 무슨 일을 하고, 각 인자가 무엇을 의미하는가"입니다. appfunctions-compiler는 Kotlin 소스코드의 KDoc 주석을 직접 파싱하여 빌드 타임에 Tool Description(함수 설명 메타데이터)으로 변환합니다.

즉, 개발자가 작성한 KDoc이 곧장 Gemini의 시스템 프롬프트/도구 설명서로 직결됩니다.


4. 실제 구현 예제 (Kotlin)

간단한 '태스크 관리 앱'에서 할 일을 생성하는 기능을 App Function으로 외부에 노출하는 예제입니다.

1) 빌드 설정 (build.gradle.kts)

plugins {
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.ksp)
}

android {
    compileSdk = 36 // Android 16 이상 필수
    // ...
}

dependencies {
    implementation("androidx.appfunctions:appfunctions:1.0.0-alpha12")
    implementation("androidx.appfunctions:appfunctions-service:1.0.0-alpha12")
    ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha12")
}

2) 데이터 모델 정의 (@AppFunctionSerializable)

함수의 입력 파라미터나 반환값으로 사용되는 복합 객체에는 @AppFunctionSerializable을 부여합니다.

import androidx.appfunctions.AppFunctionSerializable

@AppFunctionSerializable
data class CreateTaskResult(
    val taskId: String,
    val isSuccess: Boolean,
    val scheduledEpochMillis: Long
)

3) 함수 구현 (@AppFunction)

기능을 실행할 비즈니스 클래스에 함수를 정의하고, 명확하고 명령형(Imperative)인 KDoc을 작성합니다.

import android.content.Context
import androidx.appfunctions.AppFunction
import androidx.appfunctions.AppFunctionContext

class TaskFunctions(private val context: Context) {

    /**
     * 새로운 할 일(Task)을 생성하고 지정된 시간에 리마인더를 등록합니다.
     *
     * @param title 생성할 할 일의 제목
     * @param dueDateMillis 할 일의 마감 시간 (Unix Epoch Milliseconds)
     * @param priority 우선순위 (HIGH, MEDIUM, LOW 중 하나)
     * @return 생성된 작업의 고유 ID 및 등록 상태
     */
    @AppFunction
    suspend fun createTask(
        appFunctionContext: AppFunctionContext,
        title: String,
        dueDateMillis: Long,
        priority: String = "MEDIUM"
    ): CreateTaskResult {
        // 내부 데이터베이스 또는 리포지토리에 작업 등록
        val generatedId = TaskRepository.insert(
            title = title,
            dueTime = dueDateMillis,
            priority = priority
        )

        return CreateTaskResult(
            taskId = generatedId,
            isSuccess = true,
            scheduledEpochMillis = dueDateMillis
        )
    }
}

4) 서비스 진입점 선언 (@AppFunctionServiceEntryPoint)

1.0.0-alpha10 이후 단순화된 아키텍처에 따라, AppFunctionService를 상속한 추상 클래스에 @AppFunctionServiceEntryPoint를 지정합니다.

import androidx.appfunctions.service.AppFunctionService
import androidx.appfunctions.service.AppFunctionServiceEntryPoint

@AppFunctionServiceEntryPoint(TaskFunctions::class)
abstract class MyTaskAppFunctionService : AppFunctionService()

5) 매니페스트 등록 (AndroidManifest.xml)

시스템이 서비스를 탐색할 수 있도록 인텐트 필터와 권한을 등록합니다.

<service
    android:name=".MyTaskAppFunctionService"
    android:permission="android.permission.BIND_APP_FUNCTION_SERVICE"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.appfunctions.action.APP_FUNCTION_SERVICE" />
    </intent-filter>
</service>

5. 보안 및 실행 거버넌스

스마트폰에서 AI 에이전트가 백그라운드로 서드파티 앱의 함수를 마음대로 실행할 수 있다면 심각한 프라이버시 및 보안 침해가 발생할 수 있습니다. 안드로이드 플랫폼은 다음과 같은 다중 안전장치를 두고 있습니다.

  1. android.permission.EXECUTE_APP_FUNCTIONS:
    일반 서드파티 앱은 타 앱의 App Function을 호출할 수 없습니다. 시스템 서명이 있거나 OS로부터 특권(Privileged) 권한을 부여받은 공인 AI 에이전트 런타임(예: 시스템 Gemini 어시스턴트)만 호출자로 동작할 수 있습니다.
  2. BIND_APP_FUNCTION_SERVICE 보호:
    개발자의 서비스는 오직 안드로이드 시스템 프레임워크(android.permission.BIND_APP_FUNCTION_SERVICE)만이 바인딩할 수 있도록 격리됩니다.
  3. 민감 작업의 사용자 확인(Confirmation):
    송금, 결제, 데이터 영구 삭제 등 부작용(Side-effect)이 큰 기능의 경우, 에이전트가 백그라운드에서 임의 완료할 수 없도록 사전에 사용자 확인 다이얼로그나 생체 인증을 거치도록 설계 가이드가 권고됩니다.

6. 로컬 디버깅 및 테스트 (ADB)

실제 기기나 에뮬레이터에서 작성한 App Function이 시스템에 정상 등록되었는지, 올바르게 실행되는지 ADB CLI로 검증할 수 있습니다.

# 1. 등록된 모든 App Functions 목록 조회
adb shell cmd app_function list-app-functions

# 2. 특정 앱의 함수 직접 호출 테스트 (JSON 매개변수 전달)
adb shell cmd app_function execute-app-function \
  --package com.example.taskapp \
  --function-id createTask \
  --parameters '{"title":"팀 회의 준비","dueDateMillis":1790290800000,"priority":"HIGH"}'

결론: 앱의 UI 종속성 탈피와 에이전트 네이티브 시대

Android App Functions는 단순한 보조 API가 아닙니다. 모바일 앱의 가치가 '시각적 화면(Activity/Compose)'에서 '호출 가능한 기능 단위(Executable Capabilities)'로 확장되는 전환점을 의미합니다.

과거에는 사용자가 앱 아이콘을 터치하고, 메뉴를 탐색하며, 버튼을 눌러야 앱의 비즈니스 가치가 동작했습니다. 앞으로는 앱이 잘 설계된 App Functions를 노출해 두기만 하면, 사용자가 스마트폰의 AI 비서에게 자연어로 건넨 한마디만으로 앱의 핵심 로직이 백그라운드에서 자동으로 조율되고 실행됩니다.

Android 16 생태계에서 앱을 AI 친화적(AI-native)으로 진화시키기 위한 첫걸음은, 앱의 핵심 도메인 로직을 정교한 KDoc과 함께 @AppFunction으로 개방하는 것입니다.

댓글 (0)

첫 번째 댓글을 남겨보세요.