소프트웨어 엔지니어
올해 Android는 모든 UI를 빌드하는 데 Compose를 우선적으로 사용하도록 공식적으로 전환했으며, 기존 뷰는 유지보수 모드로 전환했습니다. Google Play의 경우 2020년에 이 여정이 시작되었습니다. 거의 20년에 걸쳐 수십억 명의 사용자를 대상으로 하는 엔지니어링 환경에서 Jetpack Compose로의 이전은 검증된 권장사항, 핵심 Compose팀과의 긴밀한 협업, 지속적인 도구 개선을 통해 이루어졌습니다.
Compose를 사용하여 Google Play를 현대화함으로써 속도와 장기적 안정성이 어떻게 측정 가능하게 개선되었는지 알아보세요. 이 세션에서는 에이전트형 Figma 디자인 워크플로를 Compose 구현과 연결하고, 품질을 자동화하여 불필요한 리컴포지션을 방지하고, 동적 색상, 풍부한 서체, 레이어드 도형을 사용하여 표현력이 뛰어난 인터페이스를 만드는 방법을 살펴봅니다. 이 세션을 통해 버그를 더 빠르게 분류하고 자신 있게 Compose 이전을 확장할 수 있는 검증된 전략을 얻을 수 있습니다.
ComposeView를 호스팅하는 방향으로 나아갈 수 있습니다.MaterialTheme 오버레이와 Material Color Utilities 라이브러리를 사용하여 전적으로 코드에서 작동합니다. 이렇게 하면 Activity 해체를 방지할 수 있지만 빌드 시 색 구성표를 생성하면 런타임 지연 시간을 제한하는 데 도움이 됩니다.BoxWithConstraints와 같은 잠재적인 성능 문제를 신고합니다.스크립트
안녕하세요, 여러분.
저는 존입니다.
저는 Google Play 스토어팀에서 근무하고 있습니다.
제 동료인 키릴입니다.
오늘은 뷰 및 프래그먼트 시스템에서 Compose로 많은 코드를 이전한 방법에 관해 이야기해 보겠습니다.
이제 시작해 볼까요?
도입은 어떻게 진행되었고 규모는 어느 정도였나요?
앱 코드베이스는 2007년경부터 자연스럽게 성장해 왔습니다.
수백만 줄의 프로덕션 코드, 200개의 화면, 500개의 고유한 UI 구성요소가 있으며, 이러한 구성요소는 다양한 화면에서 사용됩니다.
2020년에 Snap은 개발자 속도, 안정성, 성능이 원하는 목표에 미치지 못하기 시작했다고 판단했습니다.
그래서 최신 UI 기술 스택을 채택하기로 했습니다.
다양한 라이브러리를 평가했습니다.
당시 AndroidX의 몇몇 친구들이 Compose에 대해 이야기해 주었고, 우리는 Compose를 채택하여 Compose의 첫 번째 주요 파트너가 되기로 결정했습니다.
어땠나요?
6년이 지난 지금, Play 스토어 앱 내 사용자 노출의 97% 가 Compose 전용 화면에서 발생합니다.
2020년부터 모든 휴대전화 및 대형 화면 개발이 Compose 전용으로 전환되었습니다.
확장된 폼 팩터인 XR, TV, Auto, Wear도 2025년부터 Compose로 전환되었습니다.
Compose는 이러한 성공을 이끄는 데 큰 역할을 했으며, 이로 인해 저희는 계속해서 더 많은 Compose를 도입하고 있습니다.
매우 강력하고 포괄적인 테스트 모음이 있어 일주일에 두 번씩 새로운 버전의 Compose를 채택하는 데 도움이 되었습니다.
알파 빌드와 새로운 API를 가져오면 새로운 버그 수정, 새로운 성능 개선사항을 활용하고, 새로운 API를 살펴보고, 새로운 사용자 환경을 제공하는 데 도움이 됩니다.
특히 성능 측면에서 Compose는 모든 주요 화면에서 앱의 버벅거림 성능을 지속적으로 개선했습니다.
검색 결과 페이지, 홈페이지, 세부정보 페이지입니다.
성능, 버벅거림, 로드 지연 시간은 비즈니스와 사용자 경험에 매우 중요한 측정항목입니다.
지난 14개월 동안 30% 개선되었습니다.
그렇다면 어떻게 이런 성과를 거둘 수 있었을까요?
이것이 바로 오늘 이야기할 내용입니다.
이제 마이그레이션 계획에 대해 이야기해 보겠습니다.
이에 따라 Google Play는 다단계 접근 방식을 취했습니다.
한 번에 모든 것을 걸고 싶지는 않았습니다.
위험과 비즈니스에 미치는 영향을 파악하고 확신을 얻은 후에 본격적으로 도입했습니다.
이러한 단계를 기어가기, 걷기, 조깅, 달리기라고 부르겠습니다.
따라서 기어가는 단계는 Compose에 익숙해지는 단계였습니다.
트래픽이 적은 페이지부터 시작했습니다.
설정 페이지, 서드 파티 라이선스 등이 여기에 해당합니다.
주요 목표는 Compose 라이브러리에 익숙해지는 것입니다.
따라서 행, 열, 텍스트, 이미지 등 모든 종류의 요소에 익숙해질 수 있습니다.
그런 다음 모든 앱 인프라를 가져와 Compose 방식으로 작동하는 방식을 이해해야 합니다.
노출 로깅, 클릭 로깅, 테마 설정, 데이터 로드 개편을 동시에 진행하고 있었습니다.
이 모든 것이 해당됩니다.
특히 모든 화면이 일관되게 보이도록 하는 데 도움이 된 것은 Compose의 테마 설정 객체가 XML 스타일, 서체, 색상 등 모든 항목에 직접 매핑되는지 확인하는 단위 테스트와 기능 테스트를 빌드한 것입니다.
그래서 어느 정도 익숙해지고 편안해진 후에는 걷기로 전환하기로 했습니다.
트래픽이 매우 높은 화면에서 작은 구성요소를 가져와서 이러한 마이그레이션이 어떤 모습인지 평가했습니다.
RecyclerView에 있는 항목을 가져오는 것이 좋습니다. 이렇게 하면 뷰와 Compose 시스템 간의 호환성 문제를 이해하고 성능과 버벅거림을 측정할 수 있습니다.
구성요소 자체가 매우 복잡할 필요는 없지만 레이아웃, 텍스트, 이미지 등 일반적으로 볼 수 있는 몇 가지 다양한 인스턴스를 실행하는 것이 좋습니다.
이 영역에서 주의해야 할 점은 버벅거림과 지연 시간이 약간 증가할 수 있다는 것입니다. 이는 이제 두 개의 스택을 실행하기 때문입니다.
Compose에 모두 있는 렌더링 스택과 뷰에 있는 렌더링 스택이 있습니다.
따라서 메모리 스래싱, 추가 클래스 로드 등이 발생할 수 있습니다.
하지만 Compose를 더 많이 채택할수록 이 문제는 사라집니다.
그동안 정말로 필요한 경우 화면을 약간 미리 준비하여 화면을 정렬하고 단기적으로 비용을 줄일 수 있습니다.
걷기 다음에는 조깅으로 넘어갑니다.
이것은 우리가 매우 편안해졌을 때입니다.
트래픽이 많은 페이지에서 단일 구성요소를 실행하는 대신 트래픽이 많은 페이지 전체를 실행합니다.
이 앱에서는 탐색 라이브러리를 유지하고 프래그먼트를 사용했지만 각 개별 화면은 Compose에서 완전히 구현했습니다.
프래그먼트가 ComposeView 자체를 반환하도록 했습니다.
따라서 지연 시간과 버벅거림이 개선될 것으로 기대할 수 있습니다.
앞서 언급한 메모리 스래싱과 클래스 로드가 많이 발생하지 않습니다.
Compose 자체도 ComposeView 수준에서 어느 정도의 캐싱을 실행합니다.
따라서 일관되게 보이고 동일한 아이콘이 있을 수 있는 여러 카드가 있는 RecyclerView가 있는 경우 모든 아이콘 파싱 및 리소스 사용량이 ComposeView의 모든 항목 간에 공유됩니다.
그 후에는 달리기로 넘어갔습니다.
이때가 바로 전력을 다해야 하는 시점입니다.
앱 트래픽의 대부분이 Compose에서 발생하면 한 단계 위로 이동합니다.
따라서 화면 위에는 Activity가 있습니다.
따라서 ComposeView를 활동 루트로 이동합니다.
그리고 많은 코드가 비교적 비슷하게 보일 것입니다.
한 화면에서 다른 화면으로 이동하는 탐색 안내를 실행하려고 합니다.
하지만 프래그먼트 트랜잭션을 실행하는 대신 구성 가능한 함수를 호출합니다.
Nav2 라이브러리 또는 Nav3 라이브러리 중 원하는 라이브러리를 기반으로 이 작업을 수행할 수 있습니다.
저희는 모든 화면을 이전하지는 않았습니다.
앞서 말씀드렸듯이, Google에는 많은 데이터 센터가 있습니다.
따라서 프래그먼트 기반 화면을 사용하고 Compose의 AndroidFragment 래퍼를 활용하여 이 작업을 수행할 수 있는 프래그먼트 호환성을 빌드했습니다.
다시 한번 말씀드리지만, 버벅거림과 지연 시간은 비즈니스에 중요하므로 계속해서 한계를 뛰어넘고 있으며, 이제 화면 간 캐싱이 가능하고 메모리 스래싱 문제가 훨씬 줄어들었기 때문에 계속해서 개선되고 있습니다.
하지만 새로운 기능도 사용할 수 있습니다.
오른쪽 GIF에서 화면 간에 공유 요소 전환을 실행할 수 있는 예를 확인할 수 있습니다.
한 화면에서 다른 화면으로 이동할 때 이미지가 확대되어 연속성을 제공합니다.
전체 전환을 진행하는 동안 Compose의 모든 애니메이션 유연성을 활용할 수도 있습니다.
이제 키릴에게 마이크를 넘겨 더 많은 기능에 대해 알아보겠습니다.
존, 감사합니다.
제가 오랫동안 해 온 Android 앱의 테마 설정 및 스타일 지정이라는, 제가 매우 좋아하는 주제에 관해 이야기해 보려고 합니다.
뷰 환경에는 Java 코드와 조금 뒤에 나온 Kotlin 코드가 있었고, 그 다음에는 X-- XML 리소스, 즉 색상, 문자열, 크기, 레이아웃, 테마, 스타일과 같은 리소스가 있었습니다.
이러한 모든 XML 리소스는 APK에 포함된 리소스 테이블로 컴파일되었으며, 이는 거의 정적이었습니다.
런타임에 동적으로 사용하여 UI 계층 구조 위에 맞춤 스타일을 적용할 수 있는 API Resources.Theme.applyStyle가 있었습니다.
주요 제한사항은 콘텐츠를 확장하기 전에 이 작업을 해야 한다는 점입니다. 즉, 기존 UI에 스타일을 동적으로 적용하려면 전체 Activity를 해체하고 다시 만들어야 하므로 사용자 환경에 좋지 않았습니다.
또한 사전 컴파일된 XML 블록을 적용하고 있었기 때문에 실험 플래그나 기타 비즈니스 요구사항에 따라 여러 조건부 동적 오버레이를 서로 결합하기가 어려웠습니다.
XML 환경에서는 스타일 계층 구조의 적절한 멘탈 모델을 빌드하기가 다소 어려웠습니다.
마지막으로, Android 스튜디오나 다른 개발자 도구에는 Java 세계, 코드 세계, XML 세계 간의 격차를 해소할 수 있는 단일 통합 뷰가 없었습니다.
그래서 적절한 멘탈 모델을 구축하고 스타일이 적용되지 않는 이유, 잘못된 색상이 표시되는 이유 등을 디버그하는 것이 어려웠습니다.
새로운 Compose 환경에서는 Material Design 시스템과 Compose Material 라이브러리뿐만 아니라 다른 디자인 시스템에서도 Material Design 시스템을 위한 MaterialTheme 컴포저블이 있습니다. 이 컴포저블을 화면의 UI 계층 구조 맨 위에 적용할 수 있으며, UI의 작은 부분에 오버레이로 적용할 수도 있습니다.
오른쪽 화면을 보면 상단에 Play Points 골드가 표시되어 있습니다. 진행률 표시기와 몇 가지 텍스트가 있는 작은 카드입니다.
이 Material Theme 오버레이는 Material Color Utilities 라이브러리에서 생성된 맞춤 색 구성표와 함께 적용되며, GitHub에서 사용할 수 있습니다.
갈색, 노란색, 금색과 같은 색상을 시드로 전달하면 머티리얼 색상 토큰의 전체 스펙트럼(기본 색상, 보조 색상)이 생성되며, 이를 이 카드의 구현 내에서 사용합니다.
이를 통해 Android 개발자는 완전한 동적 테마 기능을 사용할 수 있습니다.
모든 것이 코드, 즉 Kotlin으로 이루어지므로 모든 것이 어떻게 작동하는지 적절한 정신 모델을 구축하기가 훨씬 쉽고 디버그하기도 훨씬 쉽습니다.
내부적으로 이러한 오버레이는 계층 구조에서 적용하기로 선택한 특정 UI 노드에 컴포지션 로컬로 연결됩니다.
성능 고려사항: Material Color Utilities 라이브러리로 전체 색 구성표를 생성하는 데는 비용이 듭니다.
특정 오버헤드가 발생합니다.
따라서 여러 색 구성표가 필요한 복잡한 제품(예: 도시락 상자 등)이 있고 런타임에 여러 색 구성표를 생성하는 경우, 이러한 색 구성표가 누적되면서 지연 시간과 버벅거림이 증가하기 시작합니다.
따라서 첫째, 성능에 미치는 영향을 측정해야 하고 둘째, 이 오버헤드 중 일부를 런타임에서 빌드 시간으로 오프로드할 수 있습니다.
빌드 시 동일한 Material Color Utilities 라이브러리를 사용하여 브랜딩 요구사항 또는 제품 요구사항에 따라 색 구성표를 미리 생성하고 이 오버헤드를 빌드 시로 오프로드할 수 있습니다.
앞서 언급한 CompositionLocal은 UI 계층 구조 트리에서 오버레이의 정확한 위치를 추적하므로 비용이 훨씬 적게 들지만, 여전히 무료는 아닙니다.
따라서 사용하는 수에 따라 수십, 수백 개가 누적되기 시작합니다.
그리고 어느 시점에서는 이 모든 컴포지션 로컬을 결합하는 비용을 살펴봐야 합니다.
이것이 바로 Compose의 진정한 동적 런타임 테마 설정 기능의 예입니다.
여기에는 네 개의 사분면이 있고, 동일한 시각적 요소, 동일한 이벤트 카드가 있습니다.
카드 전체에 걸쳐 있는 히어로 이미지가 있고 왼쪽 상단에 라벨, 오른쪽 하단에 버튼, 그리고 몇 가지 텍스트가 있습니다.
각 사분면의 오른쪽에는 각 요소의 디자인 사양으로 사용되는 색상 토큰의 콜아웃이 표시됩니다.
카드 구현은 이 네 가지 모두에서 동일합니다.
유일한 차이점은 카드를 래핑하는 Material Theme 오버레이가 이미지의 주요 색상(파란색, 보라색, 노란색, 빨간색)을 기반으로 동적으로 생성된 색 구성표로 생성되거나 구성된다는 것입니다.
다른 모든 것은 동일하게 유지됩니다.
활동을 해체하고 다시 만들 필요가 없습니다.
실험 플래그 또는 기타 비즈니스 요구사항에 따라 조건부로 적용할 수 있습니다.
앞서 말씀드렸듯이 앱에 색상 맞춤설정을 적용하는 훨씬 더 역동적이고 진정으로 역동적인 세상입니다.
이제 다음 섹션을 위해 존에게 다시 마이크를 넘기겠습니다.
네.
키릴이 말한 유연성이 바로 이런 것입니다.
안정성과 속도에 대해 이야기해 보겠습니다.
따라서 고품질 코드를 빠르게 빌드하는 것은 모든 개발자와 비즈니스가 원하는 바입니다.
Compose가 Play에서 이를 어떻게 지원했는지 살펴보겠습니다.
먼저, 이 큰 다이어그램에서 가장 중요한 점은 아키텍처의 단순성이 인간과 에이전트 모두를 포함한 모든 코드 작성자와 유지관리자에게 큰 이점을 제공한다는 것입니다.
이 부분에 대해 너무 깊이 들어가지는 않겠지만, Compose가 제시하는 정신 모델 중 하나는 단방향 데이터 흐름에 관한 것이며, 이는 저희 팀에 정말 큰 영향을 미쳤습니다.
작동 방식에 익숙하지 않은 분들을 위해 기본 사항을 설명하자면, 먼저 데이터 소스가 있습니다.
데이터 소스는 데이터를 제공합니다.
이 데이터는 특정 UI로 변환될 수 있으며, 이를 UI 모델로 출력합니다.
그러면 Compose는 해당 상태의 값 속성을 호출하는 것만으로 이를 쉽게 관찰할 수 있습니다.
이 다이어그램의 상단에 있는 화살표와 같습니다.
이벤트는 반대 방향으로 흐릅니다.
따라서 사용자가 버튼을 클릭하면 UI 변환기로 돌아가고 데이터 소스를 업데이트하여 새 값을 내보내고 변환이 실행되는 루프가 발생합니다.
따라서 모든 것이 비교적 간단한 루프를 통해 실행됩니다.
이러한 접근 방식의 이점은 초기 최적화 기간을 줄이는 데 도움이 된다는 것입니다.
기본 스레드나 다른 스레드에서 이러한 호출이 발생하는 위치를 더 이상 찾을 수 없습니다.
일반적인 루프를 따릅니다.
Compose를 사용하면 데이터 관찰이 매우 간단해지고 아키텍처 레이어 전반에서 데이터의 강력한 일관성이 보장됩니다.
이 멘탈 모델은 팀 내에서 정보 소스에 관한 많은 대화를 줄이고 여러 유형의 경합 상태를 완전히 제거했습니다.
또 다른 큰 이점은 이전에 사용하던 모델-뷰-컨트롤러 아키텍처와 비교했을 때 데이터 소스와 UI 변환을 병렬로 실행하는 것이 매우 간단해졌다는 것입니다.
이로 인해 스토어 내 로드 지연 시간이 50ms 정도 개선되었습니다.
정말 인상적이었습니다.
단방향 데이터 흐름과 함께 Compose의 또 다른 큰 장점은 선언적 UI입니다.
키릴이 이 점을 언급했습니다.
Play 개발자들도 이 기능을 매우 좋아합니다.
이제 UI 컨트롤 흐름이 단일 파일에 있습니다.
오른쪽에 있는 예시는 매우 간단합니다.
@Composable
fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
Row(modifier) {
Text("20% off sale")
if (LocalExpts.current.useButtonV2) {
ButtonV2("Buy", onClick = onClick)
} else {
ButtonV1("Buy", onClick = onClick)
}
}
}실험 플래그를 기반으로 두 버튼 구현 간에 전환하고 있습니다.
여러 뷰 파일이나 프래그먼트 파일, XML 파일을 읽을 필요 없이 위에서 아래로 읽기만 하면 되므로 훨씬 간단해졌습니다.
또한 컴포저블을 중첩하는 비용은 중첩된 뷰 계층 구조보다 훨씬 적으며, 성능을 위해 조금씩 짜내는 대신 코드를 자연스럽게 정렬하여 가독성을 높일 수 있습니다.
또 다른 이점은 수명 주기 콜백이 훨씬 더 간단해졌고 신경 써야 할 콜백의 수가 줄었다는 것입니다.
따라서 뷰 수명 주기, 프래그먼트 수명 주기, 활동 수명 주기를 사용하는 대신, 일회성 효과와 부작용을 사용하며, 배치하는 위치에 따라 매우 일관된 방식으로 작동합니다.
이 점이 저희에게 큰 도움이 되었습니다.
이 두 가지 아키텍처 변경사항은 LLM의 기반을 마련했으며, 이를 통해 LLM은 상당히 고품질의 코드를 생성할 수 있게 되었습니다.
여러분 중 많은 분이 좋아하는 LLM으로 이 작업을 시도해 보거나 수행해 보셨을 것입니다.
색상과 서체로 주석이 달린 스크린샷을 찍어 입력하면 행과 열, 텍스트, 버튼을 생성할 수 있으며, 꽤 괜찮은 결과물을 만들어 냅니다.
하지만 몇 가지 제한사항이 있습니다.
Play는 코드베이스를 이해하지 못합니다.
이미 빌드한 구성요소 중 재사용해야 하는 구성요소를 알지 못하며 디자인 토큰 이름도 알지 못합니다.
하드 코딩된 색상과 문자열만 제공합니다.
기기에서 가져와야 하는 콘텐츠는 무엇이고 서버에서 가져와야 하는 콘텐츠는 무엇인가요? 아니면 LazyList를 사용하고 거대한 열을 만들지 않으면서 성능을 보장하려면 어떻게 해야 하나요?
이러한 문제를 해결하기 위해 스크린샷에 메타데이터를 조금 더 추가했습니다.
UI 이름, 구성요소의 시작과 끝을 알 수 있는 경계 상자, 색상과 서체의 시맨틱 이름에 대한 디자인 토큰, 기술, 그리고 성능 고려사항을 반영할 수 있도록 배치 위치를 지정하는 프롬프트가 필요합니다.
또한 매우 높은 수준의 함수 서명을 통해 동적 콘텐츠와 정적 콘텐츠를 구분할 수 있습니다.
따라서 이전과 같은 결과가 나오고 이후로 이동합니다.
다이어그램에 노이즈가 많이 추가되므로 여기에는 경계 상자가 없습니다.
하지만 하드코딩된 색상과 서체 이름이 title large 및 on surface로 대체된 것을 확인할 수 있습니다.
카드 헤더, 아이콘 배지와 같은 구성요소 이름이 명확하게 표시되어 있습니다.
이렇게 하면 코드베이스에서 찾을 수 있습니다.
저희의 경우 이러한 요소 중 상당수가 공통 디자인 라이브러리에서 가져온 것이기도 합니다. 이에 대해서는 잠시 후에 키릴이 설명해 드릴 것입니다.
따라서 이러한 모든 항목에 항상 맞춤 라벨을 지정하지는 않습니다.
하단에 있는 OfferCard와 같은 메서드 서명과 페어링하면 제목, endDate, 이미지가 모두 동적이라는 것을 알 수 있습니다.
하드 코딩해서는 안 됩니다.
이러한 시맨틱 이름과 함께 이제 키릴이 언급한 다양한 색상 애플리케이션으로 전환할 수 있습니다.
이에 따라 훨씬 더 많은 코드가 생성되고 있습니다.
이제 키릴님에게 넘겨서 품질을 유지하는 방법에 대해 알아보겠습니다.
실제로
존, 감사합니다.
LLM 및 에이전트 지원 개발이라는 주제를 계속해서 살펴보겠습니다. 먼저 UX 디자인 측면부터 시작합니다.
Figma든 다른 도구든 선택한 디자인 도구에서 원하는 디자인 시스템의 색상 토큰, 서체 토큰, 도형 토큰이 포함된 공유 템플릿을 모든 디자이너가 사용하도록 해야 합니다.
Material일 수도 있습니다.
맞춤 디자이너 시스템일 수도 있습니다.
특히 색상 토큰의 경우, 이러한 템플릿에 밝은 모드와 어두운 모드 간 전환, 그리고 몇 년 전 Android 수준에서 도입된 일반, 중간, 높은 대비 모드 간 전환을 위한 기본 지원이 포함되기를 원합니다.
디자이너는 이러한 다양한 조합 간에 빠르게 전환하여 디자인 사양이 어떻게 반응하는지 확인할 수 있습니다.
그런 다음 내보내기 파이프라인에서 디자인이 마무리되고 구현 측으로 전달될 때, 모든 색상, 모든 서체 요소, 모든 도형이 하드코딩된 RGB 값이나 하드코딩된 글꼴 모음, 글꼴 크기 대신 일치하는 토큰을 사용하고 있는지 추적할 수 있는 기능이 필요합니다.
마지막으로, Google Play 규모에서 매우 유용하다고 생각한 것은 수십 개가 아니라 수백 개의 구성요소, 클러스터, 카드, 컨테이너가 있으며, 이들은 다양한 화면에서 사용된다는 점입니다.
이 모든 것을 한곳에서 추적하는 것이 유용하다는 것을 알게 되었습니다. 이를 구성요소 카탈로그라고 부르며, 이 구성요소 카탈로그를 기반으로 커스텀 에이전트를 학습시킵니다.
이 에이전트는 새로운 화면, 새로운 사용자 여정, 새로운 제품 영역을 시작할 때 유용합니다. 초기 디자인 탐색 단계에서 슬라이드나 Figma 사양을 에이전트에 입력하면 에이전트가 이미 존재하는 구성요소를 빠르게 식별해 줍니다. 따라서 구성요소를 다시 디자인하고 사양을 다시 작성할 필요가 없으며, 처음부터 다시 구현할 필요도 없습니다.
덕분에 설계 비용과 구현 비용을 크게 줄일 수 있습니다.
구현 측면에서는 핵심 및 맞춤 린트 규칙에 크게 의존합니다.
제가 언급하고 싶은 몇 가지 핵심 린트 규칙은 지연 시간과 버벅거림을 유발할 수 있는 불필요한 리컴포지션의 소스를 식별하는 데 도움이 되는 FrequentlyChangingValueDetector와 Material Compose Scaffold 컴포저블을 사용하지만 수신 패딩을 무시하는 경우를 신고하는 ScaffoldPaddingDetector입니다.
지연 시간과 버벅거림의 원인은 아니지만, 경우에 따라 디버깅하기 매우 어려운 레이아웃 정렬 불량(예: 에지 투 에지, 접기, 펼치기)이 발생할 수 있습니다.
마지막으로 BoxWithConstraints에는 특정 성능 고려사항이 있습니다.
모든 항목을 올바르게 배치하는 데 두 프레임이 걸릴 수 있습니다.
완전히 차단하지는 않지만 린트 경고로 표시하여 특정 화면에서 작업하는 개발자가 BoxWithConstraints를 사용하기로 선택했음을 알리거나 특정 레이아웃에 다른 것을 사용하도록 선택할 수 있습니다.
테마 자동화의 경우 색상 토큰, 서체 토큰, 도형 토큰이 있습니다.
하드 코딩된 색상과 하드 코딩된 서체의 사용을 차단하는 린트 규칙이 있습니다.
Material 2 구성요소의 사용을 신고하는 린트 규칙이 있습니다.
작년과 올해 도입된 새로운 표현력 있는 구성요소를 포함하여 최신이자 최고의 Material 3만 사용하려고 합니다.
예를 들어 기존 XML 파일에서 색상을 읽지 못하도록 하는 맞춤 린트 규칙이 있습니다.
새 화면에는 Compose를 우선적으로 사용하고 Compose만 사용하려고 합니다.
또한 Text 컴포저블, 특히 Material Design 시스템의 Text 컴포저블에는 스타일과 색상에 대한 대체가 있습니다.
로컬 콘텐츠 색상과 로컬 서체에서 읽지만 이에 의존하고 싶지는 않습니다.
모든 텍스트가 디자인 사양의 특정 스타일, 서체 스타일, 특정 색상을 의도적으로 사용하도록 해야 합니다.
이것이 Google의 린트 규칙입니다.
마지막으로 ScaffoldPaddingDetector와 마찬가지로, 모든 컴포저블 함수가 입력 수정자를 사용하도록 강제하는 맞춤 린트 규칙이 있습니다.
다시 말하지만, 새로운 사용이 잘못 배치되거나, 들어오는 배경을 존중하지 않거나, 무엇이든 간에, 이를 방지하기 위해서입니다.
이 세 가지가 이 프레젠테이션에서 기억해야 할 핵심 사항입니다.
첫 번째는 2026년 말 현재 Compose가 대규모로 검증된 성숙한 UI 툴킷이라는 점입니다.
Android 자체도 Compose 우선입니다.
올해 초 Google I/O에서 모든 UI 라이브러리와 모든 에이전트 흐름이 Compose 우선이라고 발표했습니다.
그리고 존이 앞서 프레젠테이션에서 언급했듯이, 기고, 걷고, 조깅하고, 달리는 것처럼, 특히 대규모 코드베이스의 경우 점진적으로 마이그레이션하여 개발자 흐름과 에이전트 흐름의 속도를 높이는 것이 좋습니다.
오늘 시간을 내주셔서 감사합니다. 잠시 후 저와 존이 밖에서 질문을 받겠습니다.
시간을 내주셔서 다시 한번 감사드립니다.