ART(Android Runtime)는 안드로이드 운영체제에서 앱을 실행하는 관리형 런타임 환경이다.[1] Android 4.4 KitKat(2013년)에 개발자 미리보기로 처음 공개되었고, Android 5.0 Lollipop(2014년)부터 기존 Dalvik 가상 머신을 완전히 대체하여 기본 런타임으로 자리 잡았다. ART는 애플리케이션 바이트코드를 네이티브 기계어로 변환·실행하며, 컴파일 전략·가비지 컬렉션·프로파일 기반 최적화 세 축에서 지속적으로 진화해 왔다.

1. Dalvik에서 ART로의 전환

안드로이드 초기부터 Android 4.4까지 앱 실행은 Dalvik 가상 머신이 담당했다.[1] Dalvik은 메모리가 제한된 모바일 환경에 맞게 설계된 레지스터 기반 VM으로, .dex(Dalvik Executable) 포맷의 바이트코드를 JIT 컴파일과 인터프리터를 조합해 실행했다. 그러나 앱이 복잡해지고 하드웨어 성능이 올라가면서 Dalvik의 한계—매 실행마다 반복되는 JIT 웜업 시간, 상대적으로 긴 GC 정지—가 두드러졌다.

ART는 이 문제를 AOT(Ahead-Of-Time) 컴파일로 정면 돌파했다. AOSP 기반의 Android 5.0에서는 앱 설치 또는 첫 부팅 시 .dex 바이트코드 전체를 미리 네이티브 코드(.oat 파일)로 변환해 저장했다. 이를 통해 런타임 JIT 웜업이 사라지고 앱 실행 초반부터 최고 성능을 낼 수 있게 되었다. 반면 설치 시간이 늘어나고 스토리지 사용량이 증가한다는 단점이 초기 버전의 주된 불만이었으며, 이 트레이드오프는 이후 ART 진화의 핵심 방향을 결정했다.

2. AOT·JIT 하이브리드 컴파일

Android 7.0 Nougat(2016년)부터 ART는 순수 AOT 방식에서 벗어나 AOT, JIT, 인터프리터를 결합한 하이브리드 모델을 채택했다.[2] 핵심 아이디어는 "자주 실행되는 코드만 AOT로 미리 컴파일한다"는 것이다.

  • 인터프리터: 앱 최초 설치 후 처음에는 바이트코드를 해석 실행한다. 설치 시 별도 컴파일 작업이 없어 설치 속도가 크게 빨라진다.
  • JIT 컴파일러: 실행 중 자주 호출되는 메서드를 감지해 런타임에 네이티브 코드로 컴파일하고 메모리 캐시에 저장한다.
  • 프로파일 수집: JIT는 실행 동안 어떤 메서드가 얼마나 자주 실행되는지를 기록한다.
  • 백그라운드 AOT: 기기가 유휴 상태이고 충전 중일 때, 수집된 프로파일을 바탕으로 중요 메서드만 골라 AOT 컴파일을 수행한다.

JIT 컴파일러는 AOT와 같은 최적화 패스를 공유하지만, 런타임 타입 정보 활용·더 적극적인 인라이닝·OSR(On Stack Replacement) 컴파일을 추가로 적용해 코드 품질을 더 높일 수 있다.[2] 결과적으로 설치 속도·저장 공간과 실행 성능 모두를 균형 있게 확보하는 구조가 되었다.

Android framework 계층에서 바라보면, ART는 앱 프로세스마다 독립적으로 구동되며 Zygote 프로세스에서 포크된 시점부터 이 런타임을 공유한다. Verified Boot와 함께 동작해 런타임 무결성도 보장한다.

3. 가비지 컬렉션의 진화

ART 도입 초기부터 GC는 Dalvik 대비 정지 횟수와 시간을 줄이는 방향으로 개선되었다.[3] Android 5.0~6.0 시기에는 CMS(Concurrent Mark-Sweep) 방식을 기반으로 하되, 백그라운드 전환 시점에 힙 압축을 수행해 단편화를 줄이는 방식을 사용했다.

Android 8.0 Oreo(2017년)에서 ART는 동시 압축 GC(Concurrent Copying Collector, CC) 를 기본으로 채택했다.[3] CC의 주요 특징은 다음과 같다.

  • 동시 힙 압축: 앱 스레드를 장시간 멈추지 않고도 힙을 압축한다. 스레드 루트 처리를 위한 짧은 정지 1회만 필요하다.
  • RegionTLAB 할당: 각 앱 스레드에 스레드-로컬 할당 버퍼(TLAB)를 제공해 동기화 없이 범프-포인터 방식으로 객체를 할당한다. Android 7.0 대비 할당 속도가 약 70% 향상되었다.
  • Read-Barrier: 힙에서 참조를 읽을 때 인터셉트해 동시 복사(concurrent copy)를 안전하게 수행한다.
  • 작은 정지 시간: Android 7.0 GC 대비 H2 벤치마크 기준 정지 시간이 약 85% 감소했으며, 정지 시간이 힙 크기에 비례해 늘어나지 않는다.
  • 힙 크기 절감: 압축 효과로 Android 7.0 대비 평균 32% 더 작은 힙 크기를 달성했다.

이 개선은 대화형 앱의 프레임 드롭(jank) 감소에 직접 기여했으며, 큰 힙을 사용하는 앱도 GC 부담 없이 동작할 수 있는 기반이 되었다.

4. 프로파일 기반 최적화와 베이스라인 프로파일

Android framework 생태계에서 ART의 최적화는 기기 수준을 넘어 클라우드 규모로 확장되었다. Google Play는 수억 대 기기에서 수집한 ART 실행 프로파일을 집계해, 앱 업데이트 시 이미 최적화된 .prof 파일을 함께 배포한다.[4] 앱을 처음 설치한 사용자도 이미 실사용자 패턴으로 다듬어진 AOT 컴파일 혜택을 첫 실행부터 받을 수 있다(2019년 발표).

2021년에는 베이스라인 프로파일(Baseline Profiles) 이 Jetpack을 통해 앱 개발자에게 공개되었다.[5] 베이스라인 프로파일은 개발자가 직접 "이 메서드와 클래스를 첫 실행부터 AOT 컴파일하라"고 지정하는 ART 프로파일 파일이다. Android 7.0 이상에서 동작하며, Jetpack의 ProfileInstaller 라이브러리를 통해 앱에 번들링된다. 초기 실행 성능을 크게 끌어올릴 수 있어 특히 앱 시작 속도와 스크롤 성능 개선에 효과적이다.

5. Android 버전별 주요 변화

AOSP 저장소에서 ART 소스는 art/ 디렉터리에 위치하며, 런타임 구성은 dex2oat 도구와 ART 설정 인터페이스를 통해 기기 제조사가 조정할 수 있다.[1]

6. 관련 문서

7. 인용 및 각주

[1] "Android runtime and Dalvik." Android Open Source Project. Ssource.android.com(새 탭에서 열림)

[2] "Implement ART just-in-time compiler." Android Open Source Project. Ssource.android.com(새 탭에서 열림)

[3] "Android 8.0 ART improvements." Android Open Source Project. Ssource.android.com(새 탭에서 열림)

[4] "Improving app performance with ART optimizing profiles in the cloud." Android Developers Blog, 2019. Aandroid-developers.googleblog.com(새 탭에서 열림)

[5] "Baseline Profiles overview." Android Developers. Ddeveloper.android.com(새 탭에서 열림)