버미

[안드로이드] ABB와 APK 본문

안드로이드

[안드로이드] ABB와 APK

Bum_2 2025. 8. 11. 16:12

ABB(.abb)와 APK(.apk)는 둘 다 파일의 배포를 위한 형식이다. 이 둘의 특징은 무엇이며 어떤 차이가 있는지 알아보자.


APK

Android Application Package의 약자로, 안드로이드에서 앱을 설치·실행하기 위한 배포 형식의 파일이다. 


APK 포함 내용

이 내부에는 앱의 모든 리소스(① 해상도/픽셀에 맞춘 이미지와 리소스 세트, ② UI에 표시되는 번역된 문자열, ③ ABI 등)을 하나의 파일에 포함된다.

  1. 해상도/픽셀에 맞춘 이미지와 리소스 세트
    필요한 PNG, JEPG, SVG 파일을 Drawable에 추가하는데, 해당도에 따라 mdpi ~ xxxhdpi까지 리소스가 만들어진다.

  2. UI에 표시되는 번역된 문자열
    UI에 표시되는 문자열이 번역된다. 기본 언어인 영어, 일본어, 프랑스어 등 앱이 지원하는 모든 언어 버전의 문자열 리소스가 들어간다. APK 크기가 커지는 이유 중 하나.

  3. ABI (Application Binary Interface)
    어떤 종류의 CPU에서 실행할수 있는 코드인지 결정하는 규격이다. APK에는 모든 ABI 별 .so 파일이 들어간다. 
    하지만 기기에서는 자기 CPI 아키텍처에 맞는 라이브러리만 사용한다.
    구형 ARM 기기 - 32비트 ARM - armeabi-v7a
    최신 안드로이드 기기 - 64비트 ARM - arm64-v8a
    에뮬레이터, 일부 태블릿 - 32비트 Intel - x86
    일부 고성능 기기, 에뮬레이터 - 64비트 Inter - x86_64

APK 생성 과정

생성 과정을 요약하면 다음과 같다. 소스 코드 작성 -> 컴파일 -> 패키징 -> 서명 & 정렬 & 최적화를 통해 최종 산출

 

  1. 소스 코드 작성
    Java/Kotlin 소스 코드, 레이아웃 XML, 리소스 이미지, 문자열, 네이티브 코드(C/C++)가 있다면 .cpp/.c 파일

  2. 컴파일
    • Java/Kotlin -> .class → .dex
      javac/kotlinc로 .class 생성 -> D8/R8로 .dex (Dalvik/ART 바이트 코드) 생성

    • 리소스(XML/이미지/문자열 등) →  바이너리 소스
      aapt2 가 레이아웃/values XML은 바이너리 XML를 생성, R 클래스 상수 생성(리소스 ID 매핑), PNG/Webp 등은 필요시 압축/최적화되어 포함
    • 네이티브 코드(C/C++) → .so
      NDK(CMake/ndk-build)로 ABI 별 .so 컴파일

  3. 패키징
    각 산출물은 묶는다. 그 결과 Unsigned APK가 생성된다. classes.dex(여러 개 일 수 있음), res/*(바이너리 리소스), AndroidManifext.xml(바이너리), lib//*.so, assets/*, META-INF(메타데이터) 등을 ZIP 구조로 묶고 확장자를 .apk로 지정

  4. 서명 & 정렬 & 최적화
    디버그/릴리스 키로 APK를 서명, zipalign으로 APK내부 데이터를 정렬, (선택) R8/ProGuard 난독화

  5. 최종 산출
    스토어/사이드로딩에 APK 배포

APK 설치 과정

APK는 설치 시 압축 해제되고, classes.dex (Java/Kotlin 코드), 리소스, 네이티브 라이브러리 등이 OS에 등록된다.

  1. APK 다운로드 / 전달
    Google Play, 타 앱 스토어 또는 직접 설치

  2. 서명 검증
    OS가 APK의 서명을 검사
    서명이 잘못되면 설치 불가

  3. 패키지 매니저가 APK를 /data/app/ 경로에 풀어서 저장

  4. DEX 최적화 (OAT / ART)
    APK의 안의 classes.dex를 기기용 네이티브 코드로 변환

  5. 리소스/라이브러리 등록
    resources.arsc (리소스 인덱스), .so(네이티브 라이브러리) 준비

앱 실행 과정 (런타임)

앱 실행 과정을 요약하면 다음과 같다.  AMS → Zygote fork → ART DEX 로드 & so 로드 → Application 생성 → MainActivity 실행

  1. Launcher -> ActivityManagerService(AMS) 호출
    홈 런처 앱이 인텐트 발송
    AMS가 어떤 앱을 실행할지 확인

  2. 새 프로세스 생성
    해당 앱의 UID, 프로세스 이름으로 Zygote 프로세스를 포크
    Zygote = 안드로이드 앱 프로세스 생성용 부모 프로세스 (공통 라이브러리 미리 로드)

  3. 앱 초기화
    안드로이드 런타임(ART)이 classes.dex 로드
    필요한 .so 라이브러리 로드
    리소스 매니저(ResourceManager)가 리소스 ID를 매핑

  4. Application 객체 생성
    Application.onCreate() 호출 -> 앱 전역 초기화

  5. 첫 Activity 실행
    인텐트에 따라 MainActivity.onCreate() 실행
    레이아웃 XML이 View 객체로 Inflate되어 UI 구성

  6. UI 표시 & 이벤트 루프 시작
    메인 스레드(Looper)가 이벤트를 처리하며 UI가 동작

APK가 앱 배포를 위한 최적의 구조였다면 ABB가 나오지 않았을 것이다.

 

APK의 한계는 다음과 같다.

  1. 모든 리소스를 한 파일에 포함하여 용량 낭비
    APK에는 해상도/픽셀에 맞춘 이미지와 리소스 세트, UI에 표시되는 번역된 문자열, ABI가 전부 포함된다. 

  2. 업데이트 시 전체 APK 재다운로드
    작은 수정에도 전체 APK를 새로 받아야 한다.
    따라서, 데이터 소모, 업데이트 속도 문제 발생

  3. 멀티 APK 관리 어려움
    기기별로 APK를 따로 만들고 관리하려면 개발자가 직접 빌드/업로드 해야 한다.
    스토어 관리, 버전 제어가 복잡하다.

위의 APK 한계를 뛰어넘고자 AAB가 등장했다.


AAB

Android App Bundle의 약자로 2018년 Google이 도입한 앱 배포용 패키징 형식이다. 핵심 아이디어는 앱의 모든 코드와 리소스를 하나로 묶어서 업로드하면, Google Play가 사용자 기기에 맞는 APK를 자동 생성·배포하는 것이다.

 


AAB 포함 내용

APK가 기존에 포함하고 있던 항목(해상도/픽셀에 맞춘 이미지와 리소스 세트, UI에 표시될 번역된 문자열, ABI)에 더해, BUNDLE-METADATA, 원본 리소스 압축 전 상태가 들어가있다.

  • 해상도/픽셀에 맞춘 이미지와 리소스 세트
  • UI에 표시될 번역된 문자열
  • ABI
  • BUNDLE-METADATA
    빌드 환경 정보, ProGuard/R8 매핑 파일, 서명 관련 메타데이터
  • 원본 리소스 압축 전 상태
    APK 생성 전에 최적화·분리가 가능하도록 원본 상태로 보관한다. 새 DPI 그룹이 필요하다던가, 새 CPU 아키텍처가 나왔을 때, 원본 리소스를 담고 있으면 그 형식에 맞춰 컴파일할 수 있기 때문에 이 항목이 필요하다. 


AAB 생성 과정

APK의 1, 2단계까지는 동일하다. 생성 과정을 요약하면 다음과 같다. 소스 코드 작성 -> 컴파일 -> 패키징 -> 서명 & 정렬 & 최적화를 통해 최종 산출.

 

  1. 소스 코드 작성
    Java/Kotlin 소스 코드, 레이아웃 XML, 리소스 이미지, 문자열, 네이티브 코드(C/C++)가 있다면 .cpp/.c 파일

  2. 컴파일
    • Java/Kotlin -> .class → .dex
      javac/kotlinc로 .class 생성 -> D8/R8로 .dex (Dalvik/ART 바이트 코드) 생성

    • 리소스(XML/이미지/문자열 등) →  바이너리 소스
      aapt2 가 레이아웃/values XML은 바이너리 XML를 생성, R 클래스 상수 생성(리소스 ID 매핑), PNG/Webp 등은 필요시 압축/최적화되어 포함
    • 네이티브 코드(C/C++) → .so
      NDK(CMake/ndk-build)로 ABI 별 .so 컴파일
  3. 번들링(패키징)
    Base Module(필수 코드/리소스)와 Dynamic Feature modules(선택 다운로드 기능)을 포함
    언어별, 화면 밀도별, ABI별 Config splits 정보를 함께 구조화
    실행 가능한 단일 APK가 아니라, APK 생성에 필요한 모든 코드·리소스를 모듈화하여 저장한다.

    base/ (필수 모듈)
      - dex/
      - res/
      - manifest/
      - lib/<ABI>/
      - assets/
      - resources.pb
    feature_xxx/ (동적 기능 모듈)
    BUNDLE-METADATA/ (빌드/분할/서명 관련 메타데이터)
  4. 서명
    로컬 빌드 시 개발자 키로 서명이 가능하지만, Play Store 배포 시에는 Play App Signing이 최종 서명을 처리한다. 서명 정보는 BUNDLE-METADATA 안에 포함한다.

  5. 최적화
    R8/ProGuard 로 코드 난독화 및 불필요 코드 제거
    리소스 쉬링크로 미사용 리소스 제거 가능
    구글 플레이가 기기별 APK 생성 시 압축·최적화 처리 가능하도록하여 압축은 최소화

  6. 최종 산출
    자체 실행은 불가하며 APK 변환 필수
    Google Play Console 업로드하여 play가 기기 맞춤 APK 생성 후 배포 또는 bundletool로 로컬에서 기기 맞춤 APK 생성

서명된 AAB 만들기

 

1. Build 탭 클릭

 

2. Generate Signed App Bundle /APK... 클릭

 

3. Android App Bundle(AAB) 활성화하여 Next 

 

4. (Key Store가 없다면) Create new... 클릭

 

5. Uploac Key 및 Key Store 생성

 

Key Store(키 저장소)

  • Key Store Path : 키 저장소를 생성할 위치(.jks 확장자 사용)
  • Password : 키 저장소에 사용할 보안 비밀번호를 생성
  • Confirm : Password와 같은 값

Key(키)

  • Alias : 키를 식별할 수 있는 이름
  • Password : 키에 사용할 보안 비밀번호. 해당 비밀번호는 Key Store(키 저장소) 비밀번호와 동일하게 작성한다면, 유지보수/자동화(CI/CD)에서 스크립트 관리가 간편하다. 키스토어는 빌드 서버 여러 명이 접근 가능하지만, 서명 키는 소수만 사용 가능하게 하려는 경우는 다르게 작성해도 된다.
  • Validity (years) : 키가 유효하게 유지되는 기간(년)을 설정한다. 평생 서비스 고려하여 키를 최소 25년 ~ 100년으로 설정.
  • Certificate : 소유자 정보를 입력하는 부분이다. 이 정보는 앱을 서명할 때 APK/AAB의 인증서 메타데이터에 포함된다.

서명되지 않은 AAB

이전 섹션에서는 서명된 AAB를 만드는 단계를 보여줬지만, 2번 째 단계항목에서 서명되지 않은 AAB를 만들 수도 있다. 

이는 AAB에 대한 후 처리를 하는 경우 필요하다. 전용 서명 서버에서만 서명하여 보안을 강화하거나 마켓이나 파트너별로 다른 키로 서명을 요구해, 원본 AAB 하나로 다양한 서명 라인에 투입이 가능하다.