
Android Baseline Profile은 처음 설치한 앱의 첫 실행과 주요 화면 이동에서 JIT 비용을 줄이기 위해, 어떤 코드 경로를 미리 컴파일할지 ART에 알려주는 자료입니다. Baseline Profile 적용은 Android 앱 성능 최적화를 “느낌상 빨라졌다”에서 끝내지 않고, 중요한 사용자 여정을 기록하고 Jetpack Macrobenchmark로 확인하는 작업에 가깝습니다.
앱 시작 시간이 애매하게 느린데 프로파일러를 열면 원인이 잘 보이지 않는 경우가 있습니다. 첫 설치 직후, 로그인 뒤 첫 화면, 홈 피드 첫 스크롤처럼 사용자가 바로 만지는 경로에서 체감이 커집니다. 이 글은 Baseline Profile의 개념보다 실무 흐름에 무게를 둡니다. 무엇을 기록하고, 어디에 포함되는지 확인하고, 어떤 지표로 비교해야 하는지까지 한 번에 정리합니다.

Android Baseline Profile이 필요한 이유
Android 앱은 설치 직후부터 모든 코드가 같은 속도로 실행되는 것이 아닙니다. 기기는 앱을 사용하면서 어떤 코드가 자주 실행되는지 학습하고, 그 과정에서 interpreter 실행과 JIT 컴파일을 거칩니다. 사용자가 이미 몇 번 실행한 뒤라면 Cloud Profiles나 런타임 학습의 도움을 받을 수 있지만, 첫 설치 직후에는 아직 그런 누적 정보가 부족합니다.
문제는 그 첫 순간이 앱의 인상을 결정한다는 점입니다. 첫 화면이 늦게 뜨거나, 홈 피드 첫 스크롤에서 프레임이 끊기거나, 검색 화면 진입이 버벅이면 평균 실행 시간이 괜찮아도 사용자는 “무겁다”고 느낍니다. 성능 최적화에서 평균값만 보면 놓치는 부분이 바로 여기에 있습니다.
첫 실행에서 JIT 비용이 체감되는 순간
Baseline Profile은 앱이 자주 지나가는 코드 경로를 미리 알려주는 방식입니다. 개발자가 시작, 탐색, 스크롤, 로그인 후 첫 화면 같은 critical user journey를 기록하면, 그 정보가 릴리즈 산출물에 포함됩니다. Android Runtime은 이 정보를 바탕으로 해당 경로를 AOT 컴파일할 수 있고, 사용자는 앱을 처음 열 때부터 일부 최적화 효과를 받을 수 있습니다.
Baseline Profile이 해결하는 성능 병목
Android Developers의 Baseline Profiles 개요는 포함된 코드 경로에서 첫 실행 코드 실행 속도가 약 30% 개선될 수 있다고 설명합니다. 이 숫자는 모든 앱에 고정으로 붙는 보증값이 아닙니다. 어떤 여정을 기록했는지, 앱이 Compose를 얼마나 쓰는지, R8 설정과 릴리즈 빌드 조건이 어떤지에 따라 달라집니다.

Baseline Profile은 어떻게 작동하나
Baseline Profile을 처음 보면 파일 하나를 넣으면 앱이 알아서 빨라지는 기능처럼 보이기 쉽습니다. 실무에서는 기준이 단순한 만큼 더 엄격합니다. 개발자가 “이 경로가 중요하다”고 기록한 규칙이 baseline.prof로 패키징되고, ART가 그 규칙을 참고해 설치 시점이나 실행 전후에 주요 코드를 컴파일합니다.
baseline.prof가 하는 일
릴리즈 APK에서는 assets/dexopt/baseline.prof, AAB에서는 BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof 위치를 확인합니다. 여기서 중요한 점은 “프로필 파일을 생성했다”와 “배포 산출물에 들어갔다”가 서로 다르다는 것입니다. 개발 중에는 파일이 보였는데 실제 APK Analyzer에서 빠져 있으면, ART는 설치 시점에 사용할 힌트를 받지 못합니다.
Cloud Profiles와 다른 점
Cloud Profiles는 실제 사용 데이터가 쌓인 뒤 효과가 커지는 쪽에 가깝습니다. Baseline Profile은 그와 달리 개발자가 선택한 경로를 릴리즈에 바로 실어 보냅니다. 배포 주기가 짧거나 새 사용자의 첫 경험이 중요한 앱에서는 이 차이가 꽤 큽니다. 주간 릴리즈처럼 Cloud Profiles가 충분히 모이기 전에 다음 버전이 나가는 팀이라면 더 그렇습니다.
기억할 기준
Baseline Profile은 설정 하나로 끝나는 항목이 아니라, 앱에서 먼저 빨라져야 하는 경로를 개발자가 고르는 장치입니다.

Android Baseline Profile 적용 흐름
처음 적용할 때는 Android Studio의 Baseline Profile 모듈 템플릿을 쓰는 편이 덜 헤맵니다. 이미 Macrobenchmark 모듈을 운영 중이라면 그 안에 Baseline Profile 생성 테스트를 함께 둘 수도 있습니다. 핵심은 앱 모듈과 테스트 모듈의 역할을 분리하는 것입니다.
1단계: 중요한 사용자 여정 고르기
가장 먼저 정할 것은 코드가 아니라 경로입니다. 앱 시작만 기록할지, 홈 피드 첫 스크롤까지 넣을지, 로그인 후 첫 화면까지 볼지 정해야 합니다. 실제로 작업하다 보면 모든 화면을 넣고 싶어지는데, 그 순간 프로필 유지 비용도 같이 올라갑니다. 처음에는 사용자가 가장 많이 지나가거나, 끊김이 바로 불만으로 이어지는 한두 개 경로부터 잡는 편이 낫습니다.
2단계: BaselineProfileRule로 기록하기
기록 테스트는 BaselineProfileRule을 사용합니다. 아래 예시는 최소 구조만 남긴 형태입니다. 실제 앱에서는 startActivityAndWait() 다음에 홈 화면 대기, 스크롤, 탭 이동 같은 동작을 추가해야 합니다.
@get:Rule
val baselineProfileRule = BaselineProfileRule()
@Test
fun generateBaselineProfile() {
baselineProfileRule.collect(packageName = "com.example.app") {
startActivityAndWait()
device.waitForIdle()
// 홈, 스크롤, 주요 화면 이동을 여기에 추가
}
}
startActivityAndWait()만 넣고 끝내면 시작 화면 이후의 병목은 놓치기 쉽습니다. 흔한 시행착오는 첫 실행 수치만 좋아졌는데, 손가락으로 첫 스크롤을 밀었을 때 카드 리스트가 반 박자 늦게 따라오는 문제는 그대로 남는 경우입니다. 그런 때는 홈 화면 대기, 첫 스크롤, 탭 이동을 기록에 더하고 frame timing을 다시 보는 쪽이 현실적입니다.
3단계: 앱 모듈에 연결하고 생성하기
앱 모듈에는 androidx.baselineprofile 플러그인을 적용하고, 생성 모듈을 baselineProfile 의존성으로 연결합니다. Android Developers의 Baseline Profile Gradle plugin 문서 확인일 기준(2026년 6월 14일 KST) 이 플러그인은 AGP 8.0 이상을 요구하며, 현재 프로젝트가 AGP 9.x를 쓰더라도 이것은 “최소 요구사항”과 “현재 생태계 버전”을 나누어 이해하는 편이 안전합니다.
plugins {
id("com.android.application")
id("androidx.baselineprofile")
}
dependencies {
baselineProfile(project(":baseline-profile"))
}
생성은 보통 :app:generateBaselineProfile 또는 variant별 태스크로 실행합니다. Gradle Managed Device를 쓸 때는 시스템 이미지 조건처럼 문서가 요구하는 설정을 확인해야 하고, 성능 수치 자체는 가능하면 실제 기기에서 다시 봐야 합니다.

Jetpack Macrobenchmark로 효과를 측정하는 법
Baseline Profile은 적용 자체보다 측정이 더 중요합니다. 릴리즈 산출물에 들어갔다고 해도, 사용자가 실제로 지나는 경로와 맞지 않으면 기대한 만큼 바뀌지 않을 수 있습니다. 이 때문에 Jetpack Macrobenchmark로 같은 시나리오를 두 조건에서 반복 측정합니다.
CompilationMode로 적용 전후 나누기
비교 기준은 단순합니다. CompilationMode.None()은 프로필이 없는 fresh install에 가까운 조건을 보고, CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require)는 Baseline Profile이 적용된 fresh install 조건을 봅니다. 이 둘을 같은 기기, 같은 빌드, 같은 여정으로 비교해야 해석이 흔들리지 않습니다.
@Test
fun startupWithoutProfile() =
startup(CompilationMode.None())
@Test
fun startupWithBaselineProfile() =
startup(
CompilationMode.Partial(
baselineProfileMode = BaselineProfileMode.Require
)
)
Android Developers의 Macrobenchmark 측정 문서에는 Now in Android 샘플을 Pixel 7에서 측정했을 때 no compilation 324.8ms와 Baseline Profiles 229.0ms가 제시되어 있습니다. 이 숫자는 좋은 참고점이지만, 내 앱의 결과라고 가져다 쓰면 안 됩니다. 앱 구조, 초기화 코드, 네트워크 대기, Compose 사용량이 모두 다르기 때문입니다.
TTID, TTFD, frame timing을 같이 보기
시작 시간은 TTID와 TTFD를 나누어 보는 편이 좋습니다. 첫 픽셀이 빠르게 그려져도 실제 콘텐츠가 채워지기까지 늦으면 사용자는 빠르다고 느끼지 않습니다. 화면 전환이나 스크롤을 기록했다면 slow frames, frozen frames, jank도 함께 봐야 합니다. 숫자를 많이 넣는 것보다 “시작이 빨라졌는가”와 “첫 상호작용이 부드러워졌는가”를 분리해 읽어야 원인과 개선 지점이 선명해집니다.

생성보다 중요한 검증과 디버깅
Baseline Profile에서 자주 생기는 착각은 세 가지입니다. 파일이 생성됐으니 끝났다고 생각하는 것, APK나 AAB에 들어갔는지 보지 않는 것, 기기에서 실제 컴파일 상태를 확인하지 않는 것입니다. 이 셋은 서로 다른 단계라서 하나를 통과해도 다음 단계에서 막힐 수 있습니다.
APK/AAB에 baseline.prof가 들어갔는지 확인
APK Analyzer에서 APK라면 assets/dexopt/baseline.prof를, AAB라면 BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof를 봅니다. 파일이 없으면 ProfileInstaller나 ART가 기대한 방식으로 움직일 수 없습니다. 이 단계는 자동 생성 태스크를 켰는지와 별개로 실제 산출물을 확인하는 과정입니다.
ProfileVerifier로 컴파일 상태 확인
ProfileVerifier.getCompilationStatusAsync()는 배포 뒤 상태를 해석할 때 유용합니다. benchmark 전에 프로필이 실제로 준비됐는지 확인하지 않으면, 프로필 효과가 아니라 대기 상태를 측정할 수 있습니다.
| 상태 코드 | 실무 해석 |
|---|---|
RESULT_CODE_COMPILED_WITH_PROFILE |
프로필이 설치되고 컴파일되어 기대하는 정상 상태입니다. |
RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED |
실행 중인 APK에 프로필이 없습니다. 산출물 포함 여부부터 다시 봅니다. |
RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION |
컴파일 대기 상태일 수 있습니다. 측정 전에 준비가 끝났는지 확인해야 합니다. |
자주 만나는 실패 신호
가장 흔한 실패는 debug 빌드나 잘못된 variant로 확인하는 경우입니다. 자동 생성 설정을 켰지만 instrumentation test가 불안정해서 CI에서 건너뛰어진 경우도 있습니다. 생성 로그만 보고 끝내지 말고, 산출물 확인과 기기 상태 확인을 같은 체크리스트에 넣어야 합니다.

Compose 앱과 Startup Profile까지 같이 봐야 하는 이유
Compose 앱에서는 Baseline Profile 이야기가 조금 더 중요해집니다. Compose는 플랫폼 자체가 아니라 라이브러리로 배포되기 때문에, 앱 실행 시 로드되고 필요한 시점에 해석이나 JIT 비용이 생길 수 있습니다. Compose가 기본 Baseline Profile을 제공하긴 하지만, 그것은 Compose 라이브러리 내부 코드에 대한 최적화입니다.
Compose가 제공하는 기본 프로필의 한계
내 앱의 홈 피드, 검색 결과, 상세 화면, 결제 직전 화면 같은 경로는 Compose 라이브러리가 알 수 없습니다. Compose Baseline Profile을 이야기할 때는 “Compose가 이미 제공하니 끝”이 아니라 “Compose 내부 비용은 줄지만 앱별 critical user journey는 따로 기록한다”로 이해하는 편이 맞습니다.
Baseline Profile vs Startup Profile
Startup Profile도 이름 때문에 자주 섞입니다. 둘은 경쟁 관계가 아니라 서로 다른 레이어의 최적화입니다. Baseline Profile은 ART가 코드 경로를 AOT 컴파일하도록 돕고, Startup Profile은 D8/R8이 시작 경로 중심으로 DEX 배치를 최적화하도록 돕습니다.
| 구분 | Baseline Profile | Startup Profile |
|---|---|---|
| 주요 목적 | ART가 중요한 코드 경로를 미리 컴파일하도록 돕습니다. | 시작 경로가 더 잘 로드되도록 DEX 배치를 돕습니다. |
| 범위 | 시작, 스크롤, 화면 이동 같은 여러 CUJ를 담을 수 있습니다. | 앱 시작 경로에 더 초점을 둡니다. |
| 확인 방식 | Macrobenchmark와 ProfileVerifier로 효과와 상태를 확인합니다. | DEX 배치와 시작 경로 최적화 관점에서 확인합니다. |

릴리즈와 CI에 넣을 때의 체크리스트
팀 파이프라인에 넣을 때는 자동화 욕심을 조금 조절해야 합니다. automaticGenerationDuringBuild = true를 켜면 release assemble 시 최신 프로필을 함께 생성해 포함할 수 있습니다. 그만큼 릴리즈 빌드 시간이 늘고, instrumentation test가 흔들리면 배포 파이프라인 전체가 불안정해질 수 있습니다.
자동 생성은 편하지만 CI 비용이 든다
작은 팀이라면 처음부터 모든 릴리즈 빌드에 자동 생성을 묶기보다, 명시적으로 generateBaselineProfile을 돌리고 산출물을 리뷰하는 방식이 더 안정적일 수 있습니다. 프로필이 자주 바뀌는 앱이라면 자동 생성이 유리하지만, UI 테스트가 아직 흔들리는 팀에서는 실패 원인부터 줄이는 편이 낫습니다.
어떤 여정을 먼저 기록할까
Android Calendar 사례에서는 startup 개선과 slow 또는 frozen frames 감소가 함께 보고되었습니다. Reddit 사례도 home feed, login, full-screen video player, subreddit navigation, chat처럼 사용자가 실제로 밟는 경로를 골랐습니다. Reddit의 개선은 Baseline Profiles만의 단일 결과가 아니라 R8 full mode와 Compose 업데이트 같은 여러 성능 작업이 함께 작용한 사례로 보는 편이 정확합니다.
도입 전 마지막 체크리스트
- 가장 중요한 CUJ를 한두 개로 좁혔다.
startActivityAndWait()이후 실제 스크롤이나 탐색을 기록했다.- 릴리즈 APK나 AAB 안의
baseline.prof위치를 확인했다. - ProfileVerifier로 기기 컴파일 상태를 확인했다.
- Macrobenchmark를 실제 기기에서 같은 조건으로 반복했다.
- CI에서 자동 생성 비용과 테스트 안정성을 따로 평가했다.

마무리: 하나의 여정부터 기록하고 숫자로 확인하기
Android Baseline Profile은 앱 성능을 자동으로 고쳐주는 기능이 아닙니다. 팀이 중요하다고 판단한 경로를 기록하고, 그 경로가 릴리즈 산출물에 들어갔는지 확인하고, 실제 기기에서 비교 측정해야 효과가 보입니다. 완료 기준은 “프로필을 만들었다”가 아니라 “포함했고, 컴파일 상태를 봤고, Macrobenchmark로 적용 전후를 비교했다”에 가깝습니다.
처음 시작한다면 거창하게 모든 화면을 기록하지 않아도 됩니다. 앱 시작에서 홈 첫 스크롤까지 하나의 흐름을 고르고, BaselineProfileRule로 기록한 뒤, CompilationMode.None()과 CompilationMode.Partial을 나누어 측정해 보세요. 그 결과가 의미 있게 움직이면 다음 후보는 검색, 로그인 후 첫 화면, 상세 화면 진입처럼 사용자가 실제로 답답함을 느끼는 경로에서 찾으면 됩니다.
관련 작업을 이어간다면 Android 앱 시작 성능 분석, Compose 성능 최적화, Macrobenchmark 측정 자동화 순서로 확장하는 것이 자연스럽습니다. Baseline Profile은 그 사이에 놓이는 작지만 중요한 연결점입니다. 기록한 만큼만 빨라지고, 측정한 만큼만 믿을 수 있습니다.
'코딩 > Android' 카테고리의 다른 글
| 안드로이드 면접 질문 50선 2부: Kotlin·Coroutine·Compose 심화 (0) | 2026.07.01 |
|---|---|
| 안드로이드 면접 질문 50선 (기본편) (0) | 2026.07.01 |
| Android targetSdk 37 마이그레이션 완벽가이드 (0) | 2026.06.19 |
| XML에서 Compose로 완벽 마이그레이션 - 순서부터 전략까지 (0) | 2026.03.24 |
| Android TargetSdk 36 마이그레이션 완벽 가이드 (0) | 2026.03.21 |