컴포즈 공식 가이드 읽고 분석하기 — (7)

김종식
7 min readMar 19, 2022

--

(목차로 돌아가기)

Jetpack Compose architectural layering

이 페이지는 젯팩 컴포즈로 만들 수 있는 아키텍처 레이어와 이것이 알려주는 핵심 원칙에 대하여 개략적으로 안내합니다.

젯팩 컴포즈는 단일 프로젝트가 아닙니다; 여러 모듈 조합되어 완전한 스택으로 형성되어 있습니다. 젯팩 컴포즈를 구성하는 다양한 모듈을 이해하면 다음 구성이 가능합니다.

  • 앱 또는 라이브러리를 빌드하기 위한 적정 수준의 추상화
  • 하위 레벨을 위해 세밀한 제어 또는 커스터마이징을 통해서 ‘아래로 전달’ 하는 것을 이해
  • 종속성 최소화

Layers

젯팩 컴포즈의 주요 계층은 다음과 같습니다:

그림1. 젯팩 컴포즈의 주요 계층

각 계층은 하위레벨에 구축된 기능들을 결합하여 상위 레벨의 컴포넌트를 생성합니다. 각 레이어는 하위 레이어의 모듈 바운더리 내 공개된 API 로 구축하여 필요할 경우 다른 계층으로 변경이 가능하는것을 확인할 수 있습니다.

이 계층들을 아래에서 부터 살펴보겠습니다.

Runtime

  • 이 모듈은 remember, mutableStateOf, @Composable 어노테이션 그리고 SideEffect 와 같은 컴포즈 실행에 필요한 근본(fundamentals)을 제공합니다. UI 가 아닌 Compose 의 트리 관리 기능만 필요하다면 이 계층만 빌드하는 것을 고려할 수도 있습니다.

UI

  • UI 계층은 여러 모듈로 구성됩니다. ( ui-text, ui-graphics, ui-tooling 등) 이러한 모듈들은 LayoutNode, Modifier, 입력 핸들링, 커스텀 레이아웃, 그리기 와 같은 UI 툴킷의 근본을 구현하고 있습니다. UI 툴킷의 기본 개념만 필요하다면 이 계층만 빌드하는 것을 고려할 수 있습니다.

Foundation

  • 이 모듈은 Row, Column, LazyColumn 와 같은 특정 제스쳐 인식 등 디자인 시스템에 종속되지 않은 컴포즈 UI 요소(blocks)들을 제공합니다. 당신만의 디자인 시스템을 만들려면 foundation 계층만 빌드하는 것을 고려할 수 있습니다.

Material

  • 이 모듈은 테마 시스템, 스타일 컴포넌트, 리플 표현, 아이콘 등 컴포즈 UI 를 위한 머터리얼 디자인 시스템을 제공합니다. 당신 앱에 머터리얼 디자인을 사용하고 싶다면 이 계층으로 구축하세요.

Design Principles

젯팩 컴포즈를 위한 가이드 원칙은 몇 가지 결집되어진 구성 요소를 제공하는 것이 아닌, 조립(혹은 구성) 할 수 있는 작고 기능에 집중된 조각을 제공하는 것입니다. 이러한 접근방식은 많은 이점이 있습니다.

Control

상위 수준의 컴포넌트일 수록 더 이점이 있을 수 있지만, 상위 컴포넌트가 가진 것을 직접 제어하는데는 제한적입니다. 만약 제어가 더 필요하다면, 하위수준의 컴포넌트를 사용하기 위해 ‘드롭 다운(drop down)’ 할 수 있습니다.
(* 드롭다운은 사용하려는 요소보다 좀 더 원초적으로 제공하는 API 를 사용할 수 있다는 의미로 이해했습니다. 표현이 모호하여 드롭다운 그대로 번역합니다.)

예를들어, 만약 컴포넌트의 색상을 애니메이션 처리하고 싶다면 animateColorAsState API 를 사용할 수 있습니다.

단, 컴포넌트가 항상 회색에서부터 시작되어야 한다면, 이 API 를 사용하면 안됩니다. 대신 드롭다운을 통해 더 하위 레벨의 Animatable API 를 사용할 수 있습니다.

상위 수준의 animateColorAsState API 자체는 하위 수준의 Animatable API 로 구축되어 있습니다. 하위 수준의 API 를 사용하는 것은 좀 더 복잡하지만 대신 더 정교한 컨트롤을 할 수 있습니다. 요구상황에 가장 적합한 추상화 수준을 선택하세요.

Customization

더 작게 구성된 블록에서 더 높은 수준의 구성 요소로 조합한다면 훨씬 더 쉽게 원하는대로 커스텀 컴포넌트를 만들 수 있습니다. 예를들어, Material 계층에서 제공하는 Button구현을 고려해 봅시다.

버튼은 4개의 컴포넌트로 조합되어 있습니다.

  1. 배경, 형태, 클릭 제어 등을 제공하는 Material 의 Surface
  2. 버튼이 활성 및 비활성화 되었을 때 컨텐츠 투명도를 변경하기 위한 CompositionLocalProvider
  3. 기본 텍스트 스타일을 사용할 ProvideTextStyle
  4. 기본 레이아웃 정책을 제공하기 위한 Row

구조를 좀 더 명확하게 설명하기 위해 몇몇 파라메터와 코멘트를 누락했지만, 이 4개의 버튼을 단순히 조합하여 버튼을 구현하기 때문에 컴포넌트 전체의 라인 수는 대략 40정도 됩니다. 버튼과 같은 컴포넌트들은 파라미터의 급증에 대응하기 위하여 공통요소로 가능한 것을 균형을 이루고 그 파라미터를 노출시킵니다. Material 구성요소를 예로 들면, 머터리얼 디자인 원칙을 좀 더 쉽게 따르기 위하여 특화된 공통요소를 제공합니다.

단, 컴포넌트의 파라미터를 뛰어넘는 커스터마이즈를 원한다면, 컴포넌트를 새로파서(fork) 레벨을 ‘드롭다운’ 할 수 있습니다. 예를 들어, 배경이 단색으로만 이루어진 머터리얼 디자인 버튼의 경우입니다. 그라데이션 배경이 필요한 경우, 이 옵션은 Button 의 파라미터로 제공되지 않습니다. 이런 경우 머터리얼 Button 구현체를 참조해서 자체 컴포넌트를 제작할 수 있습니다.

이렇게 구현하면 현재 컨텐츠의 투명도나 현재 텍스트 스타일과 같은 Material 계층의 컴포넌트를 계속 사용합니다. (* 참조 — 링크 문서는 테마와 관련된 내용으로 보이는데, 실제 emphasis 까지 랜딩되지는 않습니다.) 하지만 머터리얼의 SurfaceRow 로 대체하여, 원하는 모양과 스타일을 달성합니다.

주의 : 컴포넌트를 커스터마이즈 하기 위해 하위 레이어로 드롭다운 할 때, 예를들어 접근성 지원을 무시하는 것과 같은, 이로인하여 기능적으로 저하되지 않는것이 보장되어야 합니다. (그리고) 새로 판(fork) 컴포넌트가 사용되도록 지도(guide)합니다.

만약 자체적으로 구축한 디자인시스템을 이용하는 것 처럼, 머터리얼 컨셉을 전혀 사용하는 것을 원하지 않는다면, 다음과 같이 Foundation 계층의 컴포넌트들 사용하여 드롭다운 할 수 있습니다.

젯팩 컴포즈는 가장 단순한 이름을 사용하여 가장 높은 수준의 구성 요소를 제공합니다(reserves). 예를 들어, androidx.compose.material.Textandroidx.compose.foundation.text.BasicText 을 기반으로 제작되었습니다. 이는 더 높은 수준의 구성요소로 변경을 원할 때 가장 탐색하기 쉬운 이름으로 구현이 가능하도록 해줍니다.

주의 : 컴포넌트를 새로 작성(forking)하는 것은 더 상급의 컴포넌트에서 향후 추가되는 잇점이나 버그 수정의 이점을 얻을 수 없음을 의미합니다.

Picking the right abstraction

재사용 가능한 컴포즈의 계층 구성 요소를 구축하는 철학은, 항상 더 낮은 수준의 구성요소를 추구해서는 안된다는 것을 의미합니다. 많은 상위 레벨의 컴포넌트는 더 나은 기능 뿐 아니라 접근성 지원과 같은 좋은 관례를 위한 지침(best practice) 으로서 잘 구현되어 있습니다.

예를들어, 커스텀 컴포넌트에 제스처를 지원하는것을 추가하고자 하면, Modifier.pointerInput을 이용하여 처음부터 만들 수 있습니다만, 시작 관점에서 좀 더 나은 상위 컴포넌트, 예를들어 Modifier.draggable, Modifier.scrollable, Modifier.swipeable 을 이용할 수 있습니다.

원칙적으로 요구사항을 만족하는 좋은 관례를 위한 지침을 포함하여 얻을 수 있는 잇점을 위하여, 필요한 기능을 제공하는 최고 레벨의 컴포넌트 구축을 선호합니다.

--

--

김종식
김종식

Written by 김종식

앱 개발자 / 꿈은 축구선수 / 쌍둥이 아빠

No responses yet