본문 바로가기
안드로이드

안드로이드 컴파일 과정 완전정리 ⑤ 부록 - DEX 는 알겠고 APK 는요?

by kkomaeng 2026. 2. 23.

이전 글

2026.02.19 - [안드로이드] - 안드로이드 컴파일 과정 완전정리 ⑤ - DEX 란?

 

안드로이드 컴파일 과정 완전정리 ⑤ 부록 - DEX 는 알겠고 APK 는요?

이전 글에서 DEX가 Android용 바이트코드 포맷이고, D8/R8이 .class → .dex를 만든다고 정리했다. 이번 글은 그 DEX가 “어디에 담겨서 배포/설치되는가”인 APK를 다룬다.

핵심 결론부터 잡는다.

  • APK는 실행파일이 아니라 “패키지(묶음)”다. 즉, 앱을 구성하는 파일들을 한 덩어리로 포장한 컨테이너다. (Android Developers)
  • APK 안에는 보통 classes.dex, 리소스 파일들, AndroidManifest.xml, (빌드/서명 방식에 따라) 서명 관련 데이터가 들어간다. (Android Developers)
  • 설치/실행 관점에서는 “APK 안의 DEX(바이트코드)를 Android 런타임이 실행한다”로 이해하면 된다(DEX는 Android 런타임이 실행하는 바이트코드 포맷으로 문서화돼 있다). (Android Open Source Project)

1) APK를 한 문장으로 정의하면 “ZIP 아카이브”다

Android 개발자 문서는 APK 구조를 설명하면서 **“APK는 ZIP 아카이브로 구성된다”**고 못 박는다. (Android Developers)

즉 APK는 다음처럼 생각하면 된다.

  • .apk 확장자를 가진 ZIP 컨테이너
  • 컨테이너 안에 “앱 실행에 필요한 파일들”이 정해진 구조로 들어 있음

예시: APK를 열어보면 실제로 뭐가 보이나

app-release.apk를 압축 해제하면 대략 이런 트리가 나온다(프로젝트/옵션에 따라 달라질 수 있음).

AndroidManifest.xml
classes.dex
classes2.dex              (멀티덱스면)
resources.arsc
res/                      (리소스 파일)
assets/                   (원본 그대로 넣는 파일)
lib/<abi>/*.so            (네이티브 라이브러리)
META-INF/                 (v1(JAR) 서명 흔적이 여기로 보이는 경우가 많음)
...기타 파일

Android 문서에도 APK에 포함되는 항목으로 classes.dex, 리소스 파일, 컴파일된 리소스 파일(= resources.arsc) 등이 언급된다. (Android Developers)


▶ 더보기 — “패키지”라는 말의 정확한 의미

여기서 패키지는 “실행 가능한 단일 바이너리”가 아니라, 설치/배포를 위한 묶음이라는 뜻이다.
실행은 런타임(ART)이 APK 내부의 바이트코드(DEX)를 로드/실행하는 구조다. (DEX가 런타임 실행 포맷이라는 점은 공식 포맷 문서로 확인 가능) (Android Open Source Project)


2) APK 안의 핵심 파일 4종 세트

APK를 “앱이 된다”로 만드는 핵심 파일을 4개로 잡으면 이해가 빨라진다.

  1. classes.dex (코드)
  2. AndroidManifest.xml (컴포넌트/권한/메타정보)
  3. resources.arsc + res/ (리소스 테이블 + 리소스 파일들)
  4. 서명 관련 데이터(설치/업데이트의 신뢰 기반)

각각을 내부 관점으로 쪼갠다.


3) classes.dex: APK 안에 들어가는 “실행 코드”

DEX는 Android용 바이트코드 포맷이고, .dex 파일은 “클래스 정의들과 그에 연관된 데이터”를 담는다고 공식 문서가 정의한다. (Android Open Source Project)

APK 관점에서는 더 단순하게 이렇게 보면 된다.

  • classes.dex = 앱 코드의 본체(DEX 바이트코드)
  • 멀티덱스면 classes2.dex, classes3.dex … 처럼 늘어난다(여기서 “멀티덱스가 왜 생기냐”는 5편/4편에서 이어진다)

▶ 더보기 — 멀티덱스(multidex)란

DEX 파일이 하나가 아니라 여러 개인 상태를 말한다.
큰 앱에서 흔하고, 파일명이 classes.dex, classes2.dex처럼 증가한다. (“왜 여러 개가 되냐”는 이 글의 초점이 아니라서 상세 조건은 생략)


4) AndroidManifest.xml: “앱의 계약서”가 APK에 들어가는 방식

매니페스트는 앱의 구성 요소(Activity/Service/Receiver/Provider), 권한, 최소 SDK, intent-filter 같은 “앱 정의”가 들어있는 파일이다.

실무적으로 중요한 포인트는 이거다.

  • APK 내부의 AndroidManifest.xml은 종종 사람이 읽는 텍스트 XML이 아니라 “바이너리 XML 형태”로 저장된다고 알려져 있고, 모바일 보안/분석 문서에서도 “바이너리 XML이라 단순 unzip만으로 사람이 읽기 어렵다”는 설명이 있다. (mas.owasp.org)

(빌드/옵션에 따라 예외적으로 텍스트처럼 보이는 경우를 언급하는 사례도 있으니, “항상 무조건”이라고 단정하면 위험하다. 다만 일반적인 APK에서는 바이너리 형태가 흔하다는 정도로 이해하면 된다.) (Stack Overflow)


▶ 더보기 — 바이너리 XML(AXML)이란

확장자는 .xml인데 내부는 사람이 읽는 <tag>...</tag> 텍스트가 아니라,
런타임/도구가 빠르게 파싱하도록 만든 바이너리 인코딩 포맷이다. (mas.owasp.org)


5) resources.arsc + res/: “리소스를 빠르게 찾기 위한 인덱스 + 실제 파일”

Android 개발자 문서는 resources.arsc를 이렇게 설명한다.

  • resources.arsc는 **컴파일된 리소스(compiled resources)**를 담고,
  • res/values/ 계열의 XML 내용이 추출되어 바이너리 형태로 컴파일되어 아카이브된다고 적는다. (Android Developers)

즉 구조를 감으로 잡으면 이렇다.

  • resources.arsc: 리소스 테이블(문자열/스타일/ID/구성별 값 등 “빠른 조회를 위한 핵심 인덱스” 느낌)
  • res/: 레이아웃 XML, drawable, mipmap 등 실제 리소스 파일들(항상 전부가 arsc로 흡수되는 건 아님)

▶ 더보기 — “컴파일된 리소스”가 왜 필요한가

런타임이 R.string.app_name 같은 걸 빠르게 찾으려면
“문자열 이름으로 매번 파일을 뒤져서 파싱”하면 너무 느리다.

그래서 빌드 단계에서 리소스를 테이블로 만들고(= resources.arsc),
실행 시에는 ID 기반으로 빠르게 매핑한다는 그림으로 이해하면 된다. (Android Developers)


6) assets/: 리소스 시스템을 안 타는 “그대로 들어가는 파일”

assets/는 “AAPT 리소스 시스템(res/ + R.java)을 타지 않고”,
앱이 필요할 때 스트림으로 읽는 파일을 넣는 공간으로 많이 쓴다.

예시:

  • ML 모델 파일
  • 사전/룰 데이터
  • 자체 포맷의 설정 파일
  • 번들로 동봉할 큰 JSON

▶ 더보기 — assets vs res 차이(감으로 정리)

  • res/: 빌드가 리소스 ID를 부여하고(R.*), 구성별(언어/화면크기) 자동 선택이 된다
  • assets/: “파일 그대로” 들어가고, 직접 파일 경로로 읽는다

7) lib/<abi>/*.so: 네이티브 라이브러리(JNI)가 들어가는 자리

C/C++로 빌드된 .so 파일은 APK 안에 ABI별로 들어간다.

예시:

lib/arm64-v8a/libfoo.so
lib/armeabi-v7a/libfoo.so
lib/x86_64/libfoo.so

이 구조는 “단말 CPU 아키텍처마다 다른 바이너리”가 필요하기 때문에 존재한다.


▶ 더보기 — ABI란

ABI(Application Binary Interface)는 “바이너리 호환 규약” 정도로 이해하면 된다.
arm64-v8a, armeabi-v7a 같은 이름이 대표적이다.


8) APK 서명: “설치 가능/업데이트 가능”의 전제 조건

APK는 보통 서명되어야 설치/업데이트가 가능하다.
Android 공식 문서는 서명 스킴을 다음처럼 정리한다.

  • v1: JAR 서명 기반
  • v2: APK Signature Scheme v2 (Android 7.0에서 도입)
  • v3: APK Signature Scheme v3 (Android 9에서 도입) (Android Open Source Project)

또한 v2는 “whole-file signature(전체 파일 서명)”로, 검증 속도를 높이고 보호 범위의 변경을 탐지하도록 설계되었다고 문서에 적혀 있다. (Android Open Source Project)


▶ 더보기 — v1(v1 JAR)과 v2(전체 파일) 차이 감각

  • v1은 ZIP 엔트리 기반 서명(JAR 방식)이라 “파일 단위” 중심 느낌이 강하다
  • v2는 “APK 전체(보호 대상 영역)의 무결성”을 강화하고 검증을 빠르게 한다 (Android Open Source Project)

(서명 블록이 ZIP 포맷의 표준 영역이 아니라 추가 블록으로 들어간다는 설명은 문서/자료에 많지만, 여기서는 “스킴/특성”만 공식 문서로 확정 가능한 범위에서 말한다.)


9) zipalign: APK가 “패키지”인 만큼, 파일 배치도 성능에 영향을 준다

Android 문서는 zipalign을 이렇게 설명한다.

  • zipalign은 ZIP 아카이브 정렬 도구이고,
  • 압축되지 않은 파일들이 파일 시작점 기준으로 정렬되면 mmap()으로 직접 접근 가능해져서
    RAM 복사 비용을 줄이고 메모리 사용량을 줄일 수 있다고 적는다. (Android Developers)

즉 APK는 “그냥 묶기만 하면 끝”이 아니라,
컨테이너 내부 레이아웃 최적화도 실제 성능/메모리에 영향을 줄 수 있다.


▶ 더보기 — mmap이란

운영체제 기능 중 하나로, 파일 내용을 “메모리에 매핑해서” 필요할 때 페이지 단위로 읽게 하는 방식이다.
zipalign은 이 방식으로 접근하기 좋게 ZIP 내부 데이터 배치를 맞춰준다. (Android Developers)


10) 설치/실행 관점에서 APK는 어떻게 쓰이나 (DEX 글과 연결)

DEX 편에서 “DEX는 런타임이 실행하는 바이트코드”라고 했고,
이번 편에서는 그 DEX가 APK라는 패키지 안에 들어있다로 연결된다.

실행 흐름을 큰 덩어리로만 요약하면 이렇게 이해하면 된다.

  1. APK 설치
  2. 시스템이 매니페스트를 읽어서 컴포넌트/권한/메타정보를 등록(세부 구현은 버전/환경에 따라 다름)
  3. 앱 실행 시, 런타임이 APK 안의 DEX(및 관련 산출물)를 기반으로 코드를 로드/실행

“설치 후 실행 시 ART가 APK 내부 DEX를 로드한다”는 문장을 글에 넣고 싶다면,
팩트로 안전하게 쓰려면 이렇게 쓰는 편이 덜 위험하다.

  • “Android 런타임은 DEX 바이트코드를 실행하며, APK는 그 DEX를 담는 패키지다.” (Android Developers)

(설치 시점에 DEX가 어떤 형태로 최적화/캐싱되는지까지는 Android 버전/설정에 따라 달라질 수 있어서, 이 글에서 하나로 단정하지 않는다.)


11) “APK는 실행파일이 아니다” 예시 2개

예시 A) APK를 PC에서 더블클릭하면 왜 실행이 안 되나

APK는 Windows/macOS 실행파일이 아니다.
ZIP처럼 열 수는 있지만, 그 안의 classes.dex를 직접 실행하려면 Android 런타임(ART) 같은 실행 환경이 필요하다.

예시 B) “코드만 바꾸면 되지, 왜 서명이 필요하나”

APK는 배포/설치 단위고, 서명은 “이 패키지가 누가 만든 건지/중간에 바뀌지 않았는지”를 검증하는 기반이다.
특히 v2는 전체 파일 서명으로 무결성 보장 범위를 강화한다는 점이 공식 문서에 있다. (Android Open Source Project)


모를만한 단어 빠른 설명(필수)

▶ 더보기 — AAPT2가 뭐냐

AAPT2는 안드로이드 리소스 패키징 도구 체인의 일부다.
Android 문서는 AAPT2 출력물이 “실행 파일이 아니며”, 이후 단계에서 APK를 생성하기 위한 입력으로 쓰인다고 설명한다. (Android Developers)

▶ 더보기 — “APK는 ZIP”인데 왜 서명/검증 얘기가 복잡하냐

ZIP 컨테이너 위에 “안드로이드 앱 설치/업데이트” 요구사항(서명 스킴, 무결성 검증)이 얹히기 때문이다.
그래서 단순한 압축파일처럼 보이지만, 실제로는 플랫폼 정책이 강하게 개입한다. (Android Open Source Project)


참고(공식 문서 위주)

댓글