Android 라이브러리 생성

Android 라이브러리는 구조적으로 Android 앱 모듈과 동일합니다. 소스 코드, 리소스 파일 및 Android 매니페스트를 포함하여 앱을 빌드하는 데 필요한 모든 것을 포함할 수 있습니다. 하지만, Android 라이브러리는 기기에서 실행되는 APK로 컴파일되는 대신 Android 앱 모듈의 종속성으로 사용할 수 있는 AAR(Android Archive) 파일로 컴파일됩니다. JAR 파일과 달리, AAR 파일에는 Android 리소스 및 매니페스트 파일이 포함될 수 있습니다. 이를 통해 Java 클래스 및 메서드와 더불어 레이아웃 및 드로어블과 같이 공유 리소스에 번들로 구성할 수 있습니다.

라이브러리 모듈은 다음과 같은 상황에 유용합니다.

  • 액티비티, 서비스, UI 레이아웃 등의 일부 동일한 구성 요소를 사용하는 여러 앱을 빌드하는 경우.
  • 여러 APK 변형(예: 무료 및 유료 버전)에 포함되는 앱을 빌드하며 두 버전 모두에서 동일한 핵심 구성 요소가 필요한 경우.

어떠한 경우든지, 재사용하려는 파일을 라이브러리 모듈로 간단히 이동한 후 각 앱 모듈에 대한 종속성으로 라이브러리를 추가하기만 하면 됩니다. 이 페이지에서는 이 두 가지 작업을 수행하는 방법을 모두 설명합니다.

라이브러리 모듈 생성

프로젝트에서 새 라이브러리 모듈을 생성하려면 다음 단계를 진행하세요.

  1. File > New > New Module을 클릭합니다.
  2. 나타나는 Create New Module 창에서 Android Library, Next를 차례로 클릭합니다.

    일반적인 JAR 파일을 빌드하는 Java 라이브러리를 생성하는 옵션도 있습니다. JAR 파일은 많은 프로젝트에서, 특히 다른 플랫폼과 코드를 공유하려는 경우 유용하기는 하지만, JAR 파일에는 Android 프로젝트에서 코드를 재활용할 때 매우 유용한 Android 리소스 또는 매니페스트 파일을 포함할 수 없습니다. 따라서 이 가이드에서는 Android 라이브러리 생성에 대해 중점적으로 설명합니다.

  3. 라이브러리에 이름을 지정하고 라이브러리의 코드에 대한 최소 SDK 버전을 선택한 후 Finish를 클릭합니다.

Gradle 프로젝트 동기화가 완료되면 라이브러리 모듈이 왼쪽의 Project 패널에 표시됩니다. 새로운 모듈 폴더가 보이지 않을 경우 Android 뷰가 표시되어 있는지 확인합니다.

앱 모듈을 라이브러리 모듈로 변환

재활용하려는 코드가 모두 포함된 기존 앱 모듈이 있는 경우 다음과 같이 이 모듈을 라이브러리 모듈로 변환할 수 있습니다.

  1. 기존 앱 모듈의 build.gradle 파일을 엽니다. 맨 위에 다음이 표시됩니다.
    apply plugin: 'com.android.application'
    
  2. 여기에 표시된 것처럼 플러그인 할당을 변경합니다.

    apply plugin: 'com.android.library'
    
  3. Sync Project with Gradle Files를 클릭합니다.

다 되었습니다. 모듈의 전체 구조는 동일하게 유지되지만, 이제 Android 라이브러리로 작동하며 빌드에서 이제 APK 대신 AAR 파일이 생성됩니다.

라이브러리를 종속성으로 추가

Android 라이브러리의 코드를 다른 앱 모듈에 사용하려면 다음 단계를 진행하세요.

  1. 다음 두 가지 방법 중 하나로 라이브러리를 프로젝트에 추가합니다(같은 프로젝트 내에서 라이브러리 모듈을 생성한 경우에는 라이브러리 모듈이 미이 있으므로 이 단계를 건너뛸 수 있음).
    • 컴파일된 AAR(또는 JAR) 파일을 추가합니다.
      1. File > New Module을 클릭합니다.
      2. Import .JAR/.AAR Package를 클릭한 후 Next를 클릭합니다.
      3. AAR 또는 JAR 파일의 위치를 입력한 후 Finish를 클릭합니다.
    • 라이브러리 모듈을 프로젝트로 가져옵니다.
      1. File > New > Import Module을 클릭합니다.
      2. 라이브러리 모듈 디렉토리의 위치를 입력한 후 Finish를 클릭합니다.

      라이브러리 모듈이 프로젝트에 복사됩니다. 따라서 라이브러리 코드를 실제로 편집할 수 있습니다. 단일 버전의 라이브러리 코드를 유지하려는 경우 아마도 이 작업이 원하는 작업이 아닐 것이며, 그 대신 위에 설명된 대로 컴파일된 AAR 파일 가져오기 작업을 수행해야 합니다.

  2. 여기에 나와 있는 "my-library-module" 라이브러리에 대한 예시와 같이 settings.gradle 파일의 맨 윗부분에 라이브러리가 나열되는지 확인합니다.
    include ':app', ':my-library-module'
    
  3. 앱 모듈의 build.gradle 파일을 열고 다음 스니펫에 표시된 것처럼 dependencies 블록에 새 줄을 추가합니다.
    dependencies {
        compile project(":my-library-module")
    }
    
  4. Sync Project with Gradle Files를 클릭합니다.

위에 나와 있는 이 예시에서는 my-library- module이라는 Android 라이브러리 모듈이 build.gradle 파일이 상주하는 모듈의 빌드 종속성이 됩니다.

앱 모듈이 이제 Android 라이브러리에 포함된 모든 코드 및 리소스에 액세스할 수 있으며 라이브러리 AAR 파일이 빌드 시 APK에 번들로 포함됩니다.

하지만, AAR 파일을 개별적으로 공유하는 경우 project-name/module-name/build/outputs/aar/에서 이 파일을 찾을 수 있으며 Build > Make Project를 클릭하여 이 파일을 다시 생성할 수도 있습니다.

공개로 만들 리소스 선택

라이브러리에 포함된 모든 리소스는 기본적으로 공개로 설정됩니다. 모든 리소스를 묵시적으로 비공개로 만들려면 하나 이상의 특정한 특성을 공개로 정의해야 합니다. 리소스는 프로젝트의 res/ 디렉토리에 모든 파일을 포함합니다(예: 이미지). 라이브러리 사용자가 내부용으로만 사용하도록 작성된 리소스에 액세스하지 못하도록 하려면 공개 리소스를 하나 이상 선언하는 방법으로 이 자동 비공개 지정 메커니즘을 사용해야 합니다.

공개 리소스를 선언하려면 선언을 라이브러리의 public.xml 파일에 추가합니다. 이전에 공개 리소스를 추가한 적이 없으면 라이브러리의 res/values/ 디렉토리에 public.xml 파일을 생성해야 합니다.

다음 예시 코드에서는 이름이 각각 mylib_app_namemylib_public_string인 두 개의 공개 문자열 리소스를 생성합니다.

<resources>
    <public name="mylib_app_name" type="string"/>
    <public name="mylib_public_string" type="string"/>
</resources>

라이브러리를 사용하는 개발자에게 계속 표시되도록 할 모든 리소스를 공개로 만들어야 합니다. 예를 들어, v7 appcompat 라이브러리에 포함된 리소스 대부분이 비공개이더라도 툴바 위젯을 제어하는 특성은 머티리얼 디자인을 지원하기 위해 공개입니다.

특성을 비공개로 묵시적으로 만들면 라이브러리 사용자에게 내부 라이브러리 리소스에서 코드 완성 제안이 표시되지 않도록 차단될 뿐만 아니라, 라이브러리의 클라이언트를 손상시키지 않고 비공개 리소스의 이름을 바꾸거나 비공개 리소스를 제거할 수도 있습니다. 비공개 리소스는 코드 완성에서 필터링되어 제외되며, 비공개 리소스를 참조하려고 하면 테마 편집기Lint가 경고를 표시합니다.

개발 고려 사항

라이브러리 모듈 및 종속 앱을 개발할 때에는 다음 동작 및 제한 사항에 유의해야 합니다.

라이브러리 모듈에 대한 참조를 Android 앱 모듈에 추가하면 모듈의 상대적인 우선순위를 설정할 수 있습니다. 빌드 시에는 가장 낮은 우선순위에서 가장 높은 우선순위 순으로 라이브러리가 한 번에 하나씩 앱과 병합됩니다.

  • 리소스 병합 충돌

    빌드 도구는 라이브러리 모듈의 리소스를 종속 앱 모듈의 리소스와 병합합니다. 지정된 리소스 ID가 두 모듈 모두에서 정의된 경우에는 앱의 리소스가 사용됩니다.

    여러 AAR 라이브러리 간에 충돌이 발생한 경우 종속성 목록에 맨 처음(dependencies 블록의 윗부분)에 나와 있는 라이브러리의 리소스가 사용됩니다.

    일반 리소스 ID와 관련한 리소스 충돌을 방지하려면 해당 모듈에 고유하거나 모든 프로젝트 모듈 전체에 걸쳐 고유한 접두사 또는 기타 일관된 이름 지정 구성표를 사용하는 것이 좋습니다.

  • 라이브러리 모듈은 JAR 라이브러리를 포함할 수 있음

    JAR 라이브러리를 포함하는 라이브러리 모듈을 개발할 수 있습니다. 하지만 종속 앱 모듈의 빌드 경로를 수동으로 편집하고 JAR 파일에 대한 경로를 추가해야 합니다.

  • 라이브러리 모듈은 외부 JAR 라이브러리에 종속될 수 있음

    외부 라이브러리에 종속되는 라이브러리 모듈을 개발할 수 있습니다(예: Maps 외부 라이브러리). 이 경우, 종속 앱은 외부 라이브러리를 포함하는 타겟을 대상으로 빌드해야 합니다(예: Google API 추가 기능). 라이브러리 모듈 및 종속 앱 모두 매니페스트 파일의 <uses- library> 요소에서 외부 라이브러리를 선언해야 합니다.

  • 라이브러리 모듈은 원시 자산을 포함할 수 없음

    이 도구에서는 라이브러리 모듈의 assets/ 디렉토리에 저장된 원시 자산 파일을 사용할 수 없습니다. 앱에서 사용하는 모든 자산 리소스는 앱 모듈의 assets/ 디렉토리에 저장되어 있어야 합니다.

  • 앱 모듈의 minSdkVersion은 라이브러리에서 정의된 버전보다 크거나 같아야 함

    라이브러리는 종속 앱 모듈의 일부로 컴파일되므로, 라이브러리 모듈에서 사용되는 API가 앱 모듈이 지원하는 플랫폼 버전과 호환되어야 합니다.

  • 각 라이브러리 모듈은 자체적인 R 클래스를 생성함

    종속 앱 모듈을 빌드하면 라이브러리 모듈이 AAR 파일로 컴파일된 후 앱 모듈에 추가됩니다. 따라서, 각 라이브러리마다 해당 라이브러리의 패키지 이름을 따라 이름이 지정된 자체적인 R 클래스가 있습니다. 기본 모듈과 라이브러리 모듈에서 생성되는 R 클래스는 기본 모듈의 패키지와 라이브러리의 패키지를 포함하여 필요한 모든 패키지에서 생성됩니다.

  • 라이브러리 모듈이 자체적인 ProGuard 구성 파일을 포함할 수 있음

    ProGuard 구성 파일을 해당 ProGuard 지시문을 포함하는 라이브러리에 추가하여 라이브러리에서 코드 축소를 활성화할 수 있습니다. 빌드 도구는 이 파일을 라이브러리 모듈에 대해 생성된 AAR 파일 내에 포함합니다. 라이브러리를 앱 모듈에 추가하면 라이브러리의 ProGuard 파일이 앱 모듈의 ProGuard 구성 파일(proguard.txt)에 추가됩니다.

    라이브러리 모듈에 ProGuard 파일을 포함하면 라이브러리에 종속된 앱 모듈이 라이브러리를 사용하도록 ProGuard 파일을 수동으로 업데이트할 필요가 없습니다. ProGuard가 Android 앱 모듈에서 실행되는 경우 앱 모듈 및 라이브러리 모두에서 지시문을 사용하므로 라이브러리에서만 ProGuard를 실행해서는 안 됩니다.

    라이브러리의 구성 파일에 대한 이름을 지정하려면 라이브러리의 build.gradle 파일에서 defaultConfig 블록 내에 있는 consumerProguardFiles 메서드에 이름을 추가해야 합니다. 예를 들어, 다음 스니펫에서는 라이브러리의 ProGuard 구성 파일로 lib-proguard-rules.txt를 설정합니다.

    android {
        defaultConfig {
            consumerProguardFiles 'lib-proguard-rules.txt'
        }
        ...
    }
    

    앱 모듈의 디버그 빌드 유형을 사용하는 경우에도 앱 모듈은 기본적으로 라이브러리의 릴리스 빌드를 사용합니다. 라이브러리와 다른 빌드 유형을 사용하려면 앱의 build.gradle 파일에서 dependencies 블록에 종속성을 추가하고 라이브러리의 build.gradle 파일에서 publishNonDefaulttrue로 설정해야 합니다. 예를 들어, 앱의 build.gradle 파일에 다음과 같은 코드 스니펫이 지정된 경우 앱 모듈이 디버그 모드로 빌드된 경우 앱이 라이브러리의 디버그 빌드 유형을 사용하고 앱 모듈이 릴리스 모드로 빌드된 경우 라이브러리의 릴리스 빌드 유형을 사용하게 됩니다.

    dependencies {
        debugCompile project(path: ':library', configuration: 'debug')
        releaseCompile project(path: ':library', configuration: 'release')
    }
    

    또한 라이브러리의 build.gradle 파일에서 android 블록 안에 다음 줄을 추가하여 라이브러리의 비 릴리스 구성을 이를 사용하는 프로젝트에 노출해야 합니다.

    android {
        ...
        publishNonDefault true
    }
    

    하지만 publishNonDefault를 설정하면 빌드 시간이 늘어날 수 있습니다.

    라이브러리의 ProGuard 규칙으로 인해 앱 모듈에 축소와 관련하여 원치 않는 역효과가 적용되지 않도록 하려면 라이브러리에서 작동하지 않는 ProGuard 기능을 비활성화하는 규칙만 포함해야 합니다. 개발자에게 도움을 주려고 하는 규칙은 앱 모듈 또는 해당 기타 라이브러리의 기존 코드와 충돌할 수 있으므로 이를 포함하지 않아야 합니다. 예를 들어, 라이브러리의 ProGuard 파일은 앱 모듈의 최소화 작업 동안 유지해야 하는 코드가 무엇인지 지정할 수 있습니다.

    참고: Jack 툴체인에서는 ProGuard를 사용한 몇 가지 축소 및 난독 처리 옵션에 대한 지원 기능을 제공합니다.

AAR 파일에 대한 분석

AAR 파일의 확장자는 .aar이고, Maven 아티팩트 유형도 aar입니다. 파일 자체는 다음 필수 항목을 포함하는 zip 파일입니다.

  • /AndroidManifest.xml
  • /classes.jar
  • /res/
  • /R.txt

또한, AAR 파일에는 다음과 같은 선택적인 항목도 하나 이상 포함되어 있을 수 있습니다.

  • /assets/
  • /libs/name.jar
  • /jni/abi_name/name.so(여기서 abi_name은 Android에서 지원되는 ABI 중 하나임)
  • /proguard.txt
  • /lint.jar