UI 패키지 및 생성된 코드 이해

UI 패키지

UI 패키지는 유연하게 UI 정보를 교환할 수 있는 새로운 방법입니다. 디자이너는 Figma용 Relay 플러그인을 사용하여 Figma의 구성요소에서 UI 패키지를 만듭니다. 이렇게 하면 개발자가 사용할 수 있는 설계가 선언됩니다. 그런 다음 디자이너는 Figma 디자인 파일의 URL을 개발자에게 제공합니다.

개발자는 Android 스튜디오 플러그인을 사용하여 Figma 디자인 파일에서 UI 패키지를 가져옵니다. Android 스튜디오 프로젝트의 UI 패키지에는 가져온 Figma 구성요소에 관한 선언적 설명과 함께 글꼴 파일, 이미지, SVG를 비롯한 관련 애셋이 포함되어 있습니다.

UI 패키지는 영구 아티팩트이며 소스 제어에 커밋할 수 있습니다. 개발자가 Android 스튜디오 프로젝트에서 Figma 패키지를 가져오면 파일은 ui-packages 폴더 내의 프로젝트에 추가됩니다. 다음은 가져온 UI 패키지의 샘플입니다.

UI 패키지의 콘텐츠

가져온 UI 패키지가 있는 프로젝트에는 다음 파일이 포함됩니다.

  • [component_name].json - 구성요소를 설명하는 JSON 파일입니다(예: story_card.json).
  • config.json - 특정 UI 패키지의 메타데이터를 저장합니다.
  • fonts/ - 구성요소가 사용하는 글꼴 애셋이 저장된 폴더입니다(있는 경우).
  • *.png - 구성요소에 사용되는 이미지 애셋(있는 경우)입니다. 예를 들어 menu.png입니다.
  • [component_name]_preview.png - 구성요소의 미리보기 이미지입니다 (예: story_card_preview.png).
  • *.svg - 구성요소에 사용되는 벡터 그래픽 애셋입니다(있는 경우). 예를 들어 삼각형입니다.
  • FONTS.txt - 사용된 글꼴 목록입니다(있는 경우).
  • DEPS.txt - 하위 구성요소의 이름입니다.
  • VERSION.txt - UI 패키지를 만들고 가져오는 데 사용되는 Relay 버전입니다.

src/main/ui-packages/[package_name] 아래에 저장됩니다.

UI 패키지 삭제

프로젝트에서 UI 패키지를 삭제하려면 ui-packages/에서 폴더를 삭제하면 됩니다. 폴더를 삭제한 후 프로젝트를 다시 빌드하면 생성된 코드도 삭제됩니다.

생성된 코드 폴더 구조

프로젝트가 빌드되면 이러한 UI 패키지는 개발자가 호출할 수 있는 @Composable 함수를 포함하는 생성된 코드로 변환됩니다. build/generated/ 아래에 저장됩니다. Android 뷰에서는 모듈 디렉터리(이 경우 app 디렉터리) 아래에 java (generated)res로 표시됩니다.

Android 스튜디오에서 생성된 파일이 포함된 폴더

다음 스크린샷은 이 디렉터리에 있는 파일을 안내합니다.

  • 글꼴, 이미지 같은 리소스는 build/generated/res/relay/에 복사됩니다.

    res 폴더에 생성된 리소스
  • 각 UI 패키지에는 생성된 코드가 build/generated/source/relay/ 아래에 있습니다. 각 UI 패키지의 생성된 코드 폴더에는 가져온 구성요소에 상응하는 단일 파일이 있습니다. 또한 Fonts.kt로 끝나는 단일 파일도 포함되어 있으며, 여기에는 구성요소에서 사용하는 글꼴 애셋 참조가 포함되어 있습니다.

    java(생성됨) 폴더 아래에 생성된 Kotlin 파일
  • 생성된 코드에 사용되는 기능을 제공하는 런타임 라이브러리 com.google.relay.compose도 있습니다.

    Relay 런타임 라이브러리

생성된 코드 구조

컴포저블

Figma의 구성요소는 레이어로 구성됩니다. 예를 들어 아래의 디자인에는 프레임 레이어 Hello Card가 포함되어 있습니다. 이 레이어에는 두 개의 하위 레이어, 즉 Image(이미지 레이어)와 Title(텍스트 레이어)이 있습니다.

이미지 레이어와 제목 레이어가 있는 Hello Card 구성요소

이 설계가 코드로 변환되면 레이어마다 별개의 컴포저블 함수를 만듭니다. 이때 Figma 레이어의 이름은 컴포저블 함수의 이름(Kotlin 문법에 맞게 수정됨)입니다. 레이어는 다음과 같이 변환됩니다.

  1. Hello Card 레이어:

    @Composable
    fun HelloCard(
      modifier: Modifier = Modifier,
      title: String
    ) {
      TopLevel(modifier = modifier) {
          Image()
          Title(title = title)
      }
    ]
    
  2. Image 레이어:

    @Composable
    fun Image(modifier: Modifier = Modifier) {
      Image(...)
    }
    
  3. Title 레이어:

    @Composable
    fun Title(
      title: String,
      modifier: Modifier = Modifier
    ) {
      Text(...)
    }
    

변환된 Figma 변형 및 매개변수

Figma 구성요소에 여러 변형이 있는 경우 생성된 코드에는 변형 속성별 enum이 포함됩니다. 각 변형 enum의 값은 해당 변형 속성의 값에 상응합니다. 컴포저블에는 각 변형 enum의 매개변수가 포함되어 있습니다.

// Design to select for NewsCard
enum class View {
    HeroItem,
    ArticleItem,
    AudioItem
}

/**
 *   This composable was generated from the UI Package 'news_card'.
 *   Generated code; do not edit directly
 */
@Composable
fun NewsCard(
    modifier: Modifier = Modifier,
    view: View = View.HeroItem,
    onNewsCardTapped: () -> Unit = {},
    thumbnail: Painter,
    headline: String,
    author: String,
    date: String,
    onMenuTapped: () -> Unit = {}
) {
       when (view) {
           View.HeroItem -> TopLevelViewHeroItem(...) {
               ContentViewHeroItem { ... }
           }
           View.ArticleItem -> TopLevelViewArticleItem(...) {
               ContentViewArticleItem { ... }
           }
           View.AudioItem -> TopLevelViewAudioItem(...) {
               ContentViewAudioItem { ... }
           }
       }
   }
}

Figma 구성요소의 각 콘텐츠 매개변수와 상호작용 핸들러는 컴포저블의 매개변수로 변환됩니다. 아래의 NewsCard 컴포저블에는 콘텐츠 매개변수 4개(이미지 1개와 문자열 3개) 및 상호작용 핸들러 2개(마지막 2개 매개변수)가 있습니다.

/**
 *   This composable was generated from the UI Package 'news_card'.
 *   Generated code; do not edit directly
 */
@Composable
fun NewsCard(
    modifier: Modifier = Modifier,
    view: View = View.HeroItem,
    thumbnail: Painter,
    headline: String,
    author: String,
    date: String,
    onNewsCardTapped: () -> Unit = {},
    onMenuTapped: () -> Unit = {}
) {...}