면접 질문실전 질문꼬리 질문

Android Studio의 Build Analyzer

skydovesJaewoong Eum (skydoves)||11분 소요

Android Studio의 Build Analyzer

Build Analyzer는 Android Studio에 내장된 도구로, 어떤 Gradle 태스크와 플러그인이 빌드 시간에 가장 큰 영향을 미치는지 상세한 데이터를 제공하여 빌드 성능 문제를 감지하고 해결하는 데 도움을 줍니다. 빌드 간 리포트를 비교하면 성능 회귀(regression)를 식별하고, 느린 태스크를 정확하게 짚어내어 맞춤형 최적화를 적용할 수 있습니다. 이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.

  • Build Analyzer가 태스크 수준의 빌드 성능 데이터를 어떻게 제공하는지 설명할 수 있습니다.
  • always-run 태스크, 비증분(non-incremental) 어노테이션 프로세서 등 주요 경고를 식별할 수 있습니다.
  • 플러그인 뷰를 활용하여 어떤 플러그인이 비용이 큰 태스크를 유발하는지 분리해 낼 수 있습니다.
  • 빌드 리포트를 시간 순으로 비교하여 성능 회귀를 감지할 수 있습니다.
  • Build Analyzer가 제공하는 configuration cache 및 Jetifier 관련 권장 사항에 따라 조치를 취할 수 있습니다.

Build Analyzer 접근 방법

빌드를 실행할 때마다 Build Analyzer는 View > Tool Windows > Build > Build Analyzer 경로를 통해 접근할 수 있는 리포트를 생성합니다. 이 리포트는 빌드 시간에 영향을 미치는 태스크들을 실행 시간순으로 정렬하여 보여 주며, 시간이 어디에서 소비되고 있는지 즉시 파악할 수 있도록 합니다.

리포트는 빌드마다 생성되므로, 연속된 빌드 간 비교를 통해 성능 회귀를 발견하기에 좋습니다. 가령, 의존성 업그레이드 이후에 이전에 2초가 걸리던 태스크가 15초로 늘어났다면 Build Analyzer 리포트에서 해당 변화를 즉시 확인할 수 있습니다.

태스크 및 플러그인 인사이트

Plugins with tasks impacting build duration 뷰는 태스크를 해당 태스크를 등록한 플러그인별로 그룹화합니다. 느린 빌드가 직접 작성한 커스텀 태스크 때문인지, 서드파티 플러그인 때문인지, 아니면 Android Gradle Plugin 자체의 문제인지 식별하는 데 유용합니다.

각 플러그인 그룹 내에서 태스크는 실행 시간순으로 정렬됩니다. 개별 태스크를 클릭하면 입력(inputs), 출력(outputs), 증분 실행 여부, 캐시 활용 여부 등을 확인할 수 있습니다. 수십 개의 플러그인을 사용하는 프로젝트에서 전체 빌드 시간만으로는 어떤 플러그인이 성능 회귀를 유발했는지 판별하기 어려울 때 이 기능이 특히 유용합니다.

가령, 코드 생성 플러그인을 업그레이드한 후 빌드 시간이 20초 증가했다면, 플러그인 뷰에서 해당 플러그인이 등록한 구체적인 태스크와 각 태스크의 실행 시간을 확인할 수 있습니다. 이전 빌드 리포트와 비교하면 성능 회귀의 원인을 정확히 확인할 수 있습니다.

주요 경고 항목

Build Analyzer는 여러 유형의 비효율성을 경고합니다.

Always-run 태스크는 입력/출력 선언이 누락되었거나 잘못 설정되어 매 빌드마다 실행되는 태스크입니다. Gradle이 태스크 출력의 최신 여부를 판단할 수 없기 때문에 무조건 태스크를 실행하게 됩니다. 입력/출력을 올바르게 선언하면 Gradle이 결과를 캐시하여 변경 사항이 없을 때 해당 태스크를 건너뛸 수 있습니다.

올바르게 선언된 태스크의 예시는 다음과 같습니다.

abstract class GenerateConfig : DefaultTask() {
    @get:Input
    abstract val appVersion: Property<String>

    @get:OutputFile
    abstract val outputFile: RegularFileProperty

    @TaskAction
    fun generate() {
        outputFile.get().asFile.writeText(
            "version=${appVersion.get()}"
        )
    }
}

@Input@OutputFile 어노테이션을 통해 Gradle은 태스크의 최신 여부를 추적할 수 있습니다. 이 어노테이션 없이는 Gradle이 태스크를 항상 실행해야 한다고 판단합니다. 면접에서 이 부분을 설명하실 때는 "Gradle의 up-to-date 검사 메커니즘"과 연결 지어 답변하시면 좋습니다.

**태스크 설정 문제(Task setup issues)**는 여러 태스크가 동일한 출력 디렉토리에 기록할 때 발생합니다. Gradle이 출력물을 특정 태스크에 귀속시킬 수 없으므로 캐싱이 무효화됩니다. 각 태스크에 별도의 출력 디렉토리를 지정하면 해결할 수 있습니다.

**비증분 어노테이션 프로세서(Non-incremental annotation processors)**는 어떤 소스 파일이든 변경되면 어노테이션이 적용된 모든 클래스를 전체 재컴파일합니다. 증분 프로세서로 마이그레이션하거나 KSP로 전환하면 실제로 변경된 파일만 재컴파일 범위에 포함되어 빌드 속도를 크게 개선할 수 있습니다. Build Analyzer는 비증분 어노테이션 프로세서 목록을 표시해 주므로, 마이그레이션 우선순위를 쉽게 정할 수 있습니다.

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기