아무리 고성능 NPU와 AP를 탑재한 하드웨어 보드라도, 소프트웨어 스택이 최적화되어 있지 않으면 화면이 뚝뚝 끊기거나 배터리가 순식간에 녹아내리는 현상이 발생합니다. 특히 가전, 로봇, 오토모티브 등 다양한 임베디드 환경에 안드로이드 OS를 이식할 때는 한정된 리소스 안에서 최고의 퍼포먼스를 뽑아내는 시스템 튜닝 작업이 필수적입니다.
안드로이드 시스템 최적화는 감에 의존해서 코드를 수정하는 게 아닙니다. 정교한 툴로 병목 지점을 계측하고, 시스템의 전력 소비 패턴을 분석하며, 부팅 시퀀스를 밀리초(ms) 단위로 쪼개어 불필요한 태스크를 걷어내는 과정이죠. 이번 포스팅에서는 Perfetto와 Systrace를 활용한 시스템 프로파일링 기법부터 Doze 모드를 이용한 전원 관리, 그리고 bootchart를 활용한 부팅 속도 최적화까지 실무 환경에서 바로 쓸 수 있는 시스템 튜닝 기술을 깊이 있게 다뤄보겠습니다.

📌 핵심 요약 3줄
- 안드로이드 시스템 최적화는 Android Profiler, Systrace, Perfetto 등의 도구를 통해 CPU, 메모리, 그래픽 파이프라인의 병목을 정확히 계측하는 것부터 시작합니다.
- 배터리 소모를 줄이기 위해 Doze 모드와 App Standby 상태를 하드웨어 타겟에 맞게 튜닝하고, Battery Historian으로 전력 소비 패턴을 시각화 분석합니다.
- 부팅 속도는 init.rc 스크립트의 서비스 실행 시점을 지연(late_start)시키고, Bootchart를 통해 병렬 처리 최적화를 수행하여 단축합니다.
1. 안드로이드 영역별 최적화 도구 맵
시스템을 튜닝할 때 어떤 도구를 어느 레이어에 적용해야 하는지 명확하게 분류해 두면 분석 시간을 크게 줄일 수 있습니다. 각 도구의 분석 스코프를 정리한 표입니다.
| 최적화 타겟 | 분석 핵심 도구 | 측정 대상 및 데이터 | 실무 활용 목적 |
| 애플리케이션 / 프레임워크 | Android Profiler (Studio) | 힙 메모리 할당(GC), CPU 스레드 점유, 네트워크 I/O | 앱 레벨 메모리 누수 탐지 및 렌더링 스레드 지연 추적 |
| 시스템 전반 / 커널 | Perfetto / Systrace | CPU 스케줄러(Sched), 커널 컨텍스트 스위칭, 커스텀 Atrace 이벤트 | 디스플레이 프레임 드롭(Jank), 시스템 전역 락(Lock) 병목 분석 |
| 전력 및 배터리 | Battery Historian | 웨이크록(Wakelock) 상태, 앱별 전력 소비량, 시스템 알람 주기 | 백그라운드 배터리 비정상 소모 및 대기 전력 최적화 |
| 부팅 속도 | Bootchart | init 프로세스 가동 시간, 서비스별 CPU/디스크 점유율 그래프 | 초기 부팅 시퀀스 병목 구간 확인 및 init 스크립트 튜닝 |
2. 프로파일링을 통한 시스템 병목 추출
2.1 가벼운 프레임 분석을 위한 Atrace (Systrace)
atrace는 단말기 내부에서 리눅스 커널의 ftrace 서브시스템과 연결되어 그래픽 및 뷰 관련 이벤트를 빠르게 수집합니다.
# 1. 백그라운드로 그래픽, 뷰, 스케줄러 이벤트를 10초간 수집 시작
adb shell atrace --async_start -c -t 10 gfx view sched
# 2. 수집 중단 후 결과를 파일로 저장 (html 포맷으로 파싱하여 분석)
adb shell atrace --async_stop > trace.html
2.2 차세대 전역 프로파일러 Perfetto
구글이 적극적으로 밀고 있는 Perfetto를 사용하면 프로토콜 버퍼 구성 파일을 기반으로 정교한 시스템 트레이싱을 수행할 수 있습니다.
# 구성 설정 파일(.pbtxt)을 참조하여 시스템 트레이스를 수행하고 결과를 바이너리로 덤프
adb shell perfetto --txt -c /data/misc/perfetto-configs/example_config.pbtxt -o /data/misc/perfetto-traces/trace.pftrace
3. 전원 관리 및 배터리 대기 전력 최적화
임베디드 단말이 상시 전원 공급 상태가 아니라 배터리로 구동된다면, 대기 상태에서의 전력 제어가 제품의 상품성을 결정합니다.
3.1 Doze 모드 제어
안드로이드는 기기가 움직이지 않고 화면이 꺼진 상태가 지속되면 Light Doze를 거쳐 Deep Doze 단계로 진입하여 백그라운드 네트워크와 잡(Job) 실행을 강제로 제한합니다.
# 단말기의 현재 Doze 모드 상태 및 정책 설정값 덤프 확인
adb shell dumpsys deviceidle
# 테스트를 위해 강제로 Deep Doze 모드 단계를 step별로 전이시키는 명령어
adb shell dumpsys deviceidle step deep
3.2 Battery Historian 연동
배터리 소모 내역을 시각적으로 보려면 단말기의 버그리포트를 생성하여 Docker 기반의 Battery Historian 웹 뷰어에 업로드해야 합니다.
# 시스템 전반의 배터리 및 웨이크록 누적 통계가 담긴 버그리포트 추출
adb bugreport > bugreport.zip
4. 부팅 속도(Boot Time) 최적화 및 시퀀스 분석
새로운 하드웨어 보드가 켜져서 사용자가 보는 첫 화면(Launcher)이 뜨기까지의 부팅 과정을 최적화하는 단계입니다.
4.1 부팅 시퀀스 구조
안드로이드의 전원이 켜지면 시스템은 다음과 같은 흐름으로 제어권을 넘깁니다.
[Bootloader] ──> [Kernel] ──> [init] ──> [Zygote] ──> [System Server] ──> [Launcher]
4.2 init.rc 스크립트 서비스 실행 지연 기법
부팅 시점에 당장 실행되지 않아도 되는 하드웨어 진단 데몬이나 특정 벤더 서비스는 클래스를 late_start로 설정하거나 disabled 처리 후 부팅 완료 이벤트를 받고 구동시키는 것이 핵심입니다.
# /vendor/etc/init/hw/init.example.rc
service example_service /system/bin/example
class late_start # 초기 핵심 부팅 시퀀스가 끝난 후 백그라운드에서 실행되도록 설정
disabled # 시스템이 자동으로 켜지 못하게 막고, 필요할 때 start 명령으로 호출
oneshot # 일회성 실행 후 상주하지 않도록 제약
4.3 Bootchart를 이용한 부팅 시각화 분석
부팅 과정에서 어떤 서비스가 CPU와 디스크 I/O를 독점하여 병목을 유발하는지 차트로 그려주는 기능입니다.
# 1. 단말기 가동 중단 후 부팅 차트 수집 플래그 활성화
adb shell stop
adb shell setprop dev.bootchart true
adb shell start
# 2. 재부팅 후 시스템이 완전히 켜지면 /data/bootchart/ 경로에 생성된 로그 파일들을 타겟팅하여 이미지 파일로 렌더링합니다.
🛠️ 개발을 위한 팁 (Tips)
- System Server 자바 서비스 생성 최적화: 런처가 뜨기 전에 실행되는 SystemServer.java 내부를 보면 수많은 코어 서비스(PackageManager, WindowManager 등)들이 순차적으로 생성됩니다. 내가 개발하는 커스텀 하드웨어 보드에 굳이 필요 없는 기능(예: 디스플레이가 없는 IoT 보드의 WallpaperManagerService)이 소스 트리 단에서 활성화되어 있다면, SystemServer 가동 단계에서 과감히 제외해 주세요. 부팅 시간을 수백 밀리초 이상 단축할 수 있습니다.
- Perfetto 웹 UI 확장 기능 활용: perfetto로 추출한 트레이스 파일(.pftrace)을 공식 웹 뷰어(ui.perfetto.dev)에 올린 뒤, SQL 쿼리 탭을 적극적으로 활용해 보세요. 텍스트 창에 SELECT * FROM slice WHERE duration > 50000000 같은 간단한 SQL문을 작성하는 것만으로 50ms 이상 소요된 무거운 시스템 함수(Slice)들만 칼같이 필터링하여 찾아낼 수 있습니다.
⚠️ 흔히 하는 실수 (Common Mistakes)
- Zygote preloading 라이브러리의 무분별한 추가: 앱 실행 속도를 높이겠다는 목적으로 자주 쓰이는 커스텀 프레임워크 .jar 파일이나 무거운 공유 라이브러리(.so)들을 preloaded-classes나 framework.rc 파일에 과도하게 등록하는 실수를 많이 합니다. 이렇게 하면 앱 구동 속도는 약간 빨라질지 몰라도, 초기 부팅 시점에 Zygote 프로세스가 이 클래스들을 메모리에 미리 올리느라 부팅 프로세스가 수 초 이상 늘어지는 역효과가 발생합니다.
- Wakelock 해제(Release) 누락으로 인한 방전: 전원 관리 최적화를 진행할 때 센서 데이터를 주기적으로 받아오기 위해 커널이나 HAL 단에서 파워 매니저의 Wakelock을 잡는 경우가 많습니다. 이때 예외 처리 루틴에서 release()를 정상적으로 호출해 주지 않으면 단말기는 화면이 꺼진 후에도 Doze 모드로 진입하지 못하고 밤새 CPU 코어가 풀 가동되어 배터리가 방전됩니다. 항상 try-finally 블록을 활용해 자원 해제를 보장해야 합니다.
5. 결론
안드로이드 시스템 최적화는 하드웨어와 소프트웨어의 완벽한 앙상블을 만들어내는 BSP 엔지니어링의 최종 관문입니다. 아무리 훌륭한 기능도 시스템에 병목을 주거나 배터리를 고갈시킨다면 상용화 제품으로 채택될 수 없습니다.
오늘 소개한 프로파일링 도구들을 통해 시스템 내부의 지연 요소를 데이터로 계측하고, init 스크립트와 전원 정책을 정교하게 다듬어 보시길 바랍니다. 하드웨어 스펙 이상의 퍼포먼스를 이끌어내는 희열을 느껴보세요! 시스템 프로파일링 중 분석하기 까다로운 덤프 결과가 나오거나 최적화 쿼리에 대해 궁금한 점이 있다면 언제든 댓글로 남겨주세요. 같이 머리를 맞대고 풀어봅시다!
'Android System & AOSP Engineering > AOSP Framework & Custom Services' 카테고리의 다른 글
| Android Framework Service 구현 가이드: AIDL부터 Binder IPC 등록까지 (0) | 2025.05.22 |
|---|---|
| Android AOSP 아키텍처 이해: Framework Service vs System Service 차이점 (0) | 2025.05.20 |
| Android 커널 디버깅 가이드: dmesg, procfs부터 ftrace, kgdb 활용법 (0) | 2025.04.22 |
| Android 디버깅 가이드: Logcat, dumpsys, strace, systrace 실무 활용법 (0) | 2025.04.21 |
| Android 디바이스 포팅 가이드: BoardConfig 설정과 Device Tree 커널 구성 (0) | 2025.04.20 |