Jetpack Compose @Preview 구현 분석

@Preview 는 어떻게 작동될까?

Ji Sungbin
성빈랜드
5 min readDec 24, 2022

--

Photo by Stephen Kraakmo on Unsplash

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_FLAGSComposePreviewRunConfiguration 의 부모 클래스인 AndroidRunConfiguration 클래스의 변수이며, 액티비티의 Launch Options 를 나타냅니다.

AndroidRunConfiguration 는 앱을 Run 할 때 사용할 configuration 을 관리하는 클래스입니다. 최종적으로 이 클래스를 통해 PreviewActivity 의 Run 이 진행됩니다.

끝!

이번 글에선 @Preview 의 내부 구현을 알아보았습니다. 알아도 큰 도움은 되지 않지만, 단순 재미를 위해 글을 작성하였습니다.

끝까지 읽어주셔서 감사합니다.

[목차로 돌아가기]

안드로이드 개발자분들을 위한 카카오톡 오픈 채팅방을 운영하고 있습니다. 2023년 1월 1일 이후로 인원 정리가 있을 예정입니다.

--

--

Ji Sungbin
성빈랜드

Experience Engineers for us. I love development that creates references.