Android 라이브러리 만들기

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

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

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

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

라이브러리 모듈 생성

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

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

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

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

Gradle 프로젝트 동기화가 완료되면 라이브러리 모듈이 왼쪽 Project 패널에 표시됩니다. 새 모듈 폴더가 표시되지 않으면 Android 뷰를 표시하는지 확인하세요.

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

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

  1. 모듈 레벨 build.gradle 파일을 엽니다.
  2. applicationId를 지정하는 줄을 삭제합니다. Android 앱 모듈에서만 지정할 수 있습니다.
  3. 파일 상단에 다음이 표시됩니다.
        apply plugin: 'com.android.application'
        

    다음과 같이 변경합니다.

        apply plugin: 'com.android.library'
        
  4. 파일을 저장하고 File > Sync Project with Gradle Files를 클릭합니다.

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

AAR 파일을 빌드하려면 Project 창에서 라이브러리 모듈을 선택한 다음 Build > Build APK를 클릭합니다.

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

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

  1. 다음 두 가지 방법 중 하나로 라이브러리를 프로젝트에 추가합니다. 같은 프로젝트 내에서 라이브러리 모듈을 생성한 경우에는 라이브러리 모듈이 이미 있으므로 이 단계를 건너뛸 수 있습니다.
    • 컴파일된 AAR(또는 JAR) 파일을 추가합니다(라이브러리가 이미 빌드되어 있어야 함).
      1. File > New > 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 {
            implementation project(":my-library-module")
        }
        
  4. Sync Project with Gradle Files를 클릭합니다.

위의 예시에서 implementation 구성은 my-library-module이라는 라이브러리를 전체 앱 모듈의 빌드 종속성으로 추가합니다. 대신 특정 빌드 변형 전용 라이브러리를 사용하는 경우 implementation 대신 buildVariantNameImplementation을 사용하세요. 예를 들어 'pro' 제품 버전에만 라이브러리를 포함하는 경우는 다음과 같습니다.

    productFlavors {
        pro { ... }
    }
    dependencies {
        proImplementation project(":my-library-module")
    }
    

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

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

참고: 종속성 관리에 대한 자세한 내용은 변형을 인식하는 종속성 관리를 참조하세요.

공개로 만들 리소스 선택

라이브러리에 포함된 모든 리소스는 기본적으로 공개로 설정됩니다. 모든 리소스를 묵시적으로 비공개로 만들려면 하나 이상의 특정한 특성을 공개로 정의해야 합니다. 리소스는 프로젝트의 res/ 디렉터리에 모든 파일을 포함합니다(예: 이미지). 라이브러리 사용자가 내부용으로만 사용하도록 작성된 리소스에 액세스하지 못하도록 하려면 공개 리소스를 하나 이상 선언하는 방법으로 이 자동 비공개 지정 메커니즘을 사용해야 합니다. 또는 아무것도 공개로 만들지 않고 나머지(모든 리소스)를 비공개로 만드는 빈 <public /> 태그를 추가하여 모든 리소스를 비공개로 만들 수 있습니다.

공개 리소스를 선언하려면 <public> 선언을 라이브러리의 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>
    

라이브러리를 사용하는 개발자에게 계속 표시되도록 할 모든 리소스를 공개로 만들어야 합니다.

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

라이브러리를 빌드할 때 Android Gradle 플러그인이 공개 리소스 정의를 가져와서 public.txt 파일에 추출하고 이 파일은 AAR 파일 내에 패키징됩니다.

라이브러리 모듈의 개발 고려사항

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

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

  • 리소스 병합 충돌

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

    여러 AAR 라이브러리 간에 충돌이 발생한 경우 종속성 목록에 가장 먼저(dependencies 블록의 윗부분) 나열된 라이브러리의 리소스가 사용됩니다.

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

  • 다중 모듈 빌드에서는 JAR 종속성이 전이 종속성으로 처리됨

    AAR을 출력하는 라이브러리 프로젝트에 JAR 종속성을 추가하면 JAR이 라이브러리 모듈에서 처리되어 AAR과 함께 패키징됩니다.

    하지만 프로젝트에 앱 모듈에서 사용하는 라이브러리 모듈이 포함되어 있으면 앱 모듈은 라이브러리의 로컬 JAR 종속성을 전이 종속성으로 처리합니다. 이 경우 로컬 JAR은 라이브러리 모듈이 아닌 로컬 JAR을 사용하는 앱 모듈에서 처리합니다. 이를 통해 라이브러리의 코드를 변경하면 발생하는 증분 빌드 속도가 빨라집니다.

    로컬 JAR 종속성에 의한 자바 리소스 충돌은 라이브러리를 사용하는 앱 모듈에서 해결되어야 합니다.

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

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

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

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

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

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

  • 라이브러리 모듈에는 자체 ProGuard 구성 파일이 포함되어 있을 수 있음

    AAR을 빌드하고 게시하는 데 사용하는 라이브러리 프로젝트가 있는 경우 ProGuard 구성 파일을 라이브러리의 빌드 구성에 추가하면 Android Gradle 플러그인에 지정한 ProGuard 규칙이 적용됩니다. 빌드 도구는 이 파일을 라이브러리 모듈의 생성된 AAR 파일 내에 삽입합니다. 라이브러리를 앱 모듈에 추가하면 라이브러리의 ProGuard 파일이 앱 모듈의 ProGuard 구성 파일(proguard.txt)에 추가됩니다.

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

    라이브러리 프로젝트에 ProGuard 규칙을 추가하려면 라이브러리 build.gradle 파일의 defaultConfig 블록 내에 consumerProguardFiles 속성이 포함된 파일 이름을 지정해야 합니다. 예를 들어, 다음 스니펫에서는 라이브러리의 ProGuard 구성 파일로 lib-proguard-rules.txt를 설정합니다.

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

    하지만 라이브러리 모듈이 APK로 컴파일되고 AAR을 생성하지 않는 다중 모듈 빌드에 포함되어 있는 경우 라이브러리를 사용하는 앱 모듈에서만 ProGuard를 실행해야 합니다. ProGuard 규칙 및 사용법을 자세히 알아보려면 코드 및 리소스 축소를 참조하세요.

  • 라이브러리 모듈 테스트는 앱 테스트와 동일함

    가장 큰 차이는 라이브러리와 종속성이 자동으로 테스트 APK의 종속성으로 포함된다는 것입니다. 즉, 테스트 APK에는 자체 코드뿐 아니라 라이브러리의 AAR과 모든 종속성이 포함되어 있습니다. 별도의 '테스트 중인 앱'이 없으므로 androidTest 작업이 테스트 APK만 설치(및 제거)합니다.

    여러 manifest 파일을 병합하면 Gradle에서 기본 우선순위에 따라 라이브러리의 manifest를 테스트 APK의 기본 manifest에 병합합니다.

AAR 파일 분석

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

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

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

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