면접 질문실전 질문꼬리 질문

APK Analyzer와 병합된 Android Manifest

skydovesJaewoong Eum (skydoves)||10분 소요

APK Analyzer와 병합된 Android Manifest

Android Studio의 APK Analyzer는 리버스 엔지니어링 없이도 APK, AAB, ZIP 파일의 내부 구성을 검사할 수 있는 도구입니다. 개발자들이 주로 파일 크기나 DEX 메서드 수를 확인하는 용도로 사용하지만, 사실 가장 유용한 기능 중 하나는 바이너리 XML 리소스, 특히 병합된 AndroidManifest.xml을 사람이 읽을 수 있는 형태로 복원해 주는 것입니다.

매니페스트 병합(manifest merging) 과정에서 어떤 일이 일어나는지, 빌드 도구가 결과물을 어떻게 인코딩하는지, 그리고 APK Analyzer가 이를 어떻게 디코딩하는지 이해하는 것은 설정 충돌 디버깅, 라이브러리 권한 감사, 빌드 변형(variant)별 최종 매니페스트 검증 등 실무에서 매우 중요합니다. 면접에서도 APK 분석과 관련된 질문이 종종 출제되므로, 이 개념을 명확히 숙지해 두시면 좋습니다. 이 장을 학습하고 나면 다음 내용을 설명하실 수 있게 됩니다.

  • Android Gradle Plugin이 여러 매니페스트 소스를 하나의 최종 매니페스트로 병합하는 과정을 설명할 수 있습니다.
  • 병합된 매니페스트가 APK 내부에서 바이너리 XML로 인코딩되는 방식과 APK Analyzer가 이를 복원하는 원리를 이해할 수 있습니다.
  • 흔히 발생하는 매니페스트 병합 충돌과 병합 규칙이 이를 해결하는 방식을 파악할 수 있습니다.
  • 라이브러리 매니페스트가 권한, 컴포넌트, 메타데이터를 최종 애플리케이션 매니페스트에 어떻게 기여하는지 추적할 수 있습니다.
  • APK Analyzer를 활용하여 권한, 인텐트 필터, 컴포넌트 등록과 관련된 실무 문제를 진단할 수 있습니다.

안드로이드 빌드 파이프라인에서의 매니페스트 병합

안드로이드 애플리케이션은 대부분 단일 매니페스트 파일만으로 구성되지 않습니다. 메인 소스 셋인 src/main/AndroidManifest.xml에 앱의 핵심 컴포넌트를 선언하지만, 빌드 시스템은 이 외에도 여러 소스에서 매니페스트를 수집하여 통합해야 합니다. 라이브러리(AAR) 의존성은 각각 고유한 AndroidManifest.xml을 포함하고 있으며, 빌드 타입이나 제품 플레이버(product flavor) 소스 셋이 매니페스트 항목을 오버레이하거나 오버라이드할 수 있습니다. 또한 Navigation 컴포넌트 라이브러리가 인텐트 필터를 추가하는 경우도 있습니다. Android Gradle Plugin은 매니페스트 병합 도구(Manifest Merger)를 호출하여 이 모든 매니페스트를 하나의 정규 매니페스트로 결합하며, 이 결과물이 최종 APK에 포함됩니다.

병합 도구는 우선순위 순서에 따라 동작합니다. 가장 높은 우선순위는 애플리케이션의 빌드 타입별 소스 셋 매니페스트이고, 그 다음이 제품 플레이버별 매니페스트, 메인 소스 셋 매니페스트 순서이며, 가장 낮은 우선순위는 의존성 순서에 따른 라이브러리 매니페스트입니다. 두 매니페스트가 동일한 요소를 선언하는 경우, 병합 도구가 기본 규칙(default rule)과 명시적 병합 마커(merge marker)에 따라 최종 결과를 결정하게 됩니다.

// build.gradle.kts에서 병합 관련 설정 예시
android {
    buildTypes {
        release {
            // 여기서 선언한 매니페스트 항목은 메인 및 라이브러리 매니페스트보다 우선 적용됩니다
            manifestPlaceholders["appLabel"] = "MyApp"
        }
    }
}

병합 도구는 각 XML 요소를 **키 속성(key attribute)**에 따라 처리합니다. <activity>, <service>, <receiver>, <provider>의 경우 android:name이 키이며, <uses-permission> 역시 android:name을 키로 사용합니다. 동일한 키를 가진 요소가 여러 소스에 존재하면, 우선순위가 높은 소스의 속성값이 충돌하는 속성에 적용됩니다. 명확한 해결 방법이 없는 실질적인 충돌이 발생할 경우, 빌드가 매니페스트 병합 오류와 함께 실패하게 됩니다. 이 부분을 정확히 이해하고 있으면, 병합 충돌 발생 시 원인을 빠르게 파악할 수 있습니다.

병합 마커와 충돌 해결

개발자는 tools 네임스페이스의 tools: 속성을 추가하여 병합 동작을 직접 제어할 수 있습니다. 이러한 마커는 특정 요소나 속성을 어떻게 처리할지 병합 도구에 지시합니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- 라이브러리가 추가한 권한을 제거 -->
    <uses-permission
        android:name="android.permission.ACCESS_FINE_LOCATION"
        tools:node="remove" />

    <!-- 라이브러리의 액티비티 선언을 대체 -->
    <activity
        android:name="com.library.SomeActivity"
        android:exported="false"
        tools:node="replace" />

    <!-- 전체 노드가 아닌 특정 속성만 오버라이드 -->
    <application
        android:allowBackup="false"
        tools:replace="android:allowBackup" />
</manifest>

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기