Jetpack Compose @Preview 구현 분석
@Preview 는 어떻게 작동될까?
Jetpack Compose 는 @Preview
어노테이션을 통해 컴포저블 미리보기를 지원합니다.
이런 @Preview
어노테이션은 어떻게 작동될까요? 이번 글에선 @Preview
의 내부 작동을 소개합니다.
Owner
모든 컴포저블은 렌더링되기 위해선 Owner 의 지정이 필요합니다. Owner 란 컴포즈 내부 개념이며, 안드로이드 뷰 시스템과 상호 작용을 위임해 주는 역할을 담당합니다.
우리는 컴포즈를 ComponentActivity#setContent
를 통해 시작하고 있으며, 이 부분에서 Owner 지정이 진행됩니다.
하지만 @Preview 를 사용할 때는 Owner 를 지정하는 코드를 작성한 적이 없습니다. 그렇다면 @Preview 를 통한 컴포저블 렌더링은 어떻게 가능할까요?
PreviewActivity
정답은 PreviewActivity 에 있습니다. 모든 @Preview 컴포저블은 tooling 아티팩트에 위치한 PreviewActivity 라는 Preview 전용 액티비티에 호스팅됩니다.
액티비티의 intent 에서 “composable” string key 를 찾아 setComposableContent
를 진행합니다.
인자의 composableFqn 는 @Preview 를 받은 컴포저블의 fully-qualified name(이하 fqn)을 의미합니다. 인자로 받은 fqn 을 substring 하여 class name 과 method name 을 구분하고 있고, 해당 값들로 ComposableInvoker#invokeComposable
을 진행하고 있습니다.
만약 parameter provider 가 사용됐다면 setParameterizedContent
를 대신 사용합니다. 2가지 방식 모두 원리는 동일하므로 전자의 경우만 보도록 하겠습니다.
invokeComposable 는 인자로 받은 class name 과 method name 에 일치하는 컴포저블 Method 를 찾고, 해당 Method 를 invoke 하는 작업으로 구성돼 있습니다.
만약 setComposableContent
단계에서 setParameterizedContent
가 진행됐다면 args 인자로 해당 parameterized 값이 들어옵니다.
컴포저블 Method 를 찾는 방법으론 class name 의 Class 에 findComposableMethod
를 호출합니다.
findComposableMethod
는 해당 Class 를 순회하며 주어진 인자와 method name 에 일치하는 Method 를 반환합니다.
찾은 Method 는 invokeComposableMethod
함수를 통해 invoke 됩니다.
invokeComposableMethod
는 상황에 맞게 사용할 arguments 를 계산하고 invoke 하는 로직으로 구성돼 있습니다.
이렇게 setComposableContent
-> invokeComposable
-> findComposableMethod
-> invokeComposableMethod
과정을 거쳐 최종적으로 @Preview 가 렌더링됩니다. 결국 @Preview 는 별도의 액티비티에서 리플랙션에 의존하며 구현된다는 걸 확인할 수 있습니다.
Android Studio 의 @Preview 작업
@Preview 를 렌더링하는 작업은 순수히 Android Studio 에서 진행됩니다. 오직 PreviewActivity 와 ComposableInvoker 만이 Compose-Tooling 에 구현돼 있습니다.
PreviewActivity 의 Intent 설정은 @Preview 를 디바이스/에뮬레이터로 Run 하는 클래스인 DeployToDeviceAction 에서 진행됩니다.
만약 @Preview 를 렌더링해야 한다고 요청이 들어오면 DeployToDeviceAction#runPreviewConfiguration
이 실행됩니다.
위 함수의 8~14번 줄을 보면 ComposePreviewRunConfiguration
인스턴스를 만들고 name
, composableMethodFqn
, provider~
을 설정하고 있습니다.
ComposePreviewRunConfiguration
은 PreviewActivity 를 launch 할 때 사용할 Intent 의 configuration 을 담당하는 클래스이며, composableMethodFqn
, provider~
가 설정될 때마다 ACTIVITY_EXTRA_FLAGS
를 조정하게 됩니다.
ACTIVITY_EXTRA_FLAGS
는 ComposePreviewRunConfiguration
의 부모 클래스인 AndroidRunConfiguration
클래스의 변수이며, 액티비티의 Launch Options 를 나타냅니다.
AndroidRunConfiguration
는 앱을 Run 할 때 사용할 configuration 을 관리하는 클래스입니다. 최종적으로 이 클래스를 통해 PreviewActivity 의 Run 이 진행됩니다.
끝!
이번 글에선 @Preview 의 내부 구현을 알아보았습니다. 알아도 큰 도움은 되지 않지만, 단순 재미를 위해 글을 작성하였습니다.
끝까지 읽어주셔서 감사합니다.
안드로이드 개발자분들을 위한 카카오톡 오픈 채팅방을 운영하고 있습니다. 2023년 1월 1일 이후로 인원 정리가 있을 예정입니다.