안드로이드

Compose 훑어보기

코딩하는후운 2022. 11. 10. 10:22
반응형

선언형 UI 프레임워크 란?

  1. 2017년 5월 구글, 크로스 플랫폼 프레임워크 플러터 공개.
  2. 2019년 6월 애플, UI 개발을 위한 프레임워크 Swift UI 추가.
  3. 2020년 1월 구글, Jetpack Compose 0.1.0-dev04 버전 공개.

→ 선언형(Declarative) UI  패러다임이 적용되고 있음

 

명령형 UI 방식

// Imperative style
b.setColor(red)
b.clearChildren()
ViewC c3 = new ViewC(...)
b.add(c3)

이미 그려진 뷰의 속성을 수정한다.

 

 

Android 의 기존 작업 방식

1. 기획서를 보고 레이아웃 XML을 만든다.
2. 관련된 스타일 Resource 를 작업한다. 
3. XML을 코드로된 뷰에서 로드하고, 각 뷰에 데이터를 바인딩한다.

→ 하나의 화면을 그리기 위해 필요한 파일이 많고, 작성해야하는 라인수도 적지 않음

→ 특히 XML 작성에 많은 시간이 소요되며, 재작업 도 빈번하게 일어나는 편임

 

 

선언형 UI 의 방식에는 State 가 존재한다.

// Declarative style
return ViewB(
  color: red,
  child: ViewC(...),
)

상태 즉 “무엇을” 렌더링할지 정의해주면 자세한 부분은 프레임워크에서 처리

상태 값이 변경되면 새로운 화면을 다시 생성(Recomposition) 하는 방식

 

 

선언형의 공식

  • 같은 상태에 대해서는 항상 똑같은 View를 리턴
  • UI 는 뷰 단위로 구성 (플러터에서는 위젯 Compose 에서는 @Composable 함수)
  • 이 뷰는 부모 자식간의 관계를 형성 (플러터에서는 위젯트리, Compose 에서는 펑션트리)

 

 

 

Compose 개요

  • 앱 UI를 렌더링할 수 있게 하는 선언형 API를 제공
  • 앱 UI를 더 쉽게 작성하고 유지관리할 수 있도록 지원

→ 개발자들의 UI 작업의 생산성을 높여줄 수 있음.

 

  • 현재 1.1.1 버전까지 릴리즈 되었으며, 계속해서 업데이트 될 예정
  • 여러 UI 라이브러리들이 이미 Compose 를 지원하고 있음

→ 앞으로 업데이트나 개선이 멈추는 일은 없어 보임

Compose 기본

1. Composable 함수

  • @Composable이 함수가 데이터를 UI로 변환하기 위한 함수라는 것을 Compose 컴파일러에 알려줌
  • 매개변수를 받을 수 있으며, 아무것도 반환하지 않음(화면에 대한 작업이므로)
  • 이 함수는 멱등원이며 부작용이 없음 → 항상 같은 방식으로 동작한다.

 

2. 동적 컨텐츠

@Composable
fun Greeting(names: List<String>) {
    for (name in names) {
        Text("Hello $name")
    }
}

 

3. Recomposition

  • 재구성은 입력이 변경될 때 구성 가능한 함수를 다시 호출하는 프로세스
  • 변경되었을 수 있는 함수 또는 람다만 호출하고 나머지는 패스한다
    • 실행이 될 수도 있고 아닐 수도 있다 → 중요한 로직, 공유변수가 컴포저블의 실행에 의존해서는 안된다.
    • 공유 객체의 속성, 공유 환경 값(Preferences) 을 write 하지 않아야한다.

4. Recomposition skips as much as possible

/**
 * Display a list of names the user can click with a header
 */
@Composable
fun NamePicker(
    header: String,
    names: List<String>,
    onNameClicked: (String) -> Unit
) {
    Column {
        // this will recompose when [header] changes, but not when [names] changes
        Text(header, style = MaterialTheme.typography.h5)
        Divider()

        // LazyColumn is the Compose version of a RecyclerView.
        // The lambda passed to items() is similar to a RecyclerView.ViewHolder.
        LazyColumn {
            items(names) { name ->
                // When an item's [name] updates, the adapter for that item
                // will recompose. This will not recompose when [header] changes
                NamePickerItem(name, onNameClicked)
            }
        }
    }
}

/**
 * Display a single name the user can click.
 */
@Composable
private fun NamePickerItem(name: String, onClicked: (String) -> Unit) {
    Text(name, Modifier.clickable(onClick = { onClicked(name) }))
}
  • 기존 방식에서 화면 업데이트 성능 향상을 위해 뷰를 플랫하게(ConstraintLayout) 작성하는것과 다르다. 컴포즈에서는 해당 블럭 자체를 건너띄우고 상태가 변경된 것만 갱신할 수 있다.

 

5. Jetpack Compose Phases

  • 컴포지션: 표시할 UI입니다. Compose는 구성 가능한 함수를 실행하고 UI 설명을 만듭니다.
  • 레이아웃: UI를 배치할 위치입니다. 이 단계는 측정과 배치라는 두 단계로 구성됩니다. 레이아웃 요소는 레이아웃 트리에 있는 각 노드의 레이아웃 요소 및 모든 하위 요소를 2D 좌표로 측정하고 배치합니다.
  • 그리기: 렌더링하는 방법입니다. UI 요소는 일반적으로 기기 화면인 캔버스에 그려집니다.

 

 

 

Compose 장점

1. 빠른 개발 속도, 코드 감소, 유연한 유지 보수

  • 컴포즈가 아닌 방식으로 개발하려고 했다면, 아마도 꽤 많은 코드를 작성해야 했을 것이다.

 

 

2. View(Model) - Layout 간의 결합도를 낮추고 응집도를 높힌다.

  • 결합도 : 결합도는 서로 다른 모듈 간에 상호 의존하는 정도 또는 연관된 관계를 의미 → 최소화
  • 응집도 : 응집도는 한 모듈 내부의 처리 요소들이 서로 관련되어 있는 정도 → 최대화

  • Android 에서는 일반적으로 이런 구조가 된다. 더군다나 xml 은 여러개 만들어야할 수도 있다.

  • UI 를 소스코드와 같은 언어로 작성하고, 결합도를 낮추고 응집력은 높은 구조를 만든다.

 

3. UI객체를 다시 생성 하므로 개발자가 변수와 UI객체간의 연결고리에 대하여 고민할 필요가 없다.

  • FindViewById, Butterknife, ViewBinding, DataBinding … 등에서 벗어난다.

 

4. 용량, 빌드 타임 감소

  • Compose Only 사용하는 경우에만 장점이 될 수 있다

 

5. 프레임워크에 기반한 성능

  • Smart recompositions : Compose는 업데이트해야 하는 부분만 재구성하기 위해 최선을 다합니다.

 

6. Compose 로 리스트 만들기 예시

https://developer.android.com/jetpack/compose/lists?hl=ko 

 

목록 및 그리드  |  Jetpack Compose  |  Android Developers

목록 및 그리드 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 많은 앱에서 항목의 컬렉션을 표시해야 합니다. 이 문서에서는 Jetpack Compose에서 이 작업을 효

developer.android.com

 

Compose를 사용하기 위해 알아야 할 것들

1. 상태 관리

  • Compose는 선언적. Compose를 업데이트하는 유일한 방법은 새 인수로 동일한 컴포저블을 호출
  • 인수 값 → UI 상태 값. 이 값의 관리가 필요함

2. 수명주기

3. 부수효과

4. 단계

Compose 예제 살펴보기

  • JetNews

 

  • JetNews 에서 상태관리에 사용한 StateFlow 이해하기

https://developer.android.com/kotlin/flow/stateflow-and-sharedflow?hl=ko 

 

StateFlow 및 SharedFlow  |  Android 개발자  |  Android Developers

StateFlow 및 SharedFlow 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. StateFlow와 SharedFlow는 흐름에서 최적으로 상태 업데이트를 내보내고 여러 소비자에게 값을

developer.android.com

 

Compose 사용의 이슈들

1. 쉬운데 어렵다.

  • 처음 보고 화면 몇장 그렸을때는 쉬운데 본격적으로 쓰고자 한다면? 아 이거 쉽지 않다.
  • 제대로 성능 내려면 Compose Only 여야하는데, 꽤 깊은 수준의 이해가 필요하다.

 

2. 지금까지 알아왔던(?) 많은 것을 버려야한다.

  • 기존에 사용했던 XML과 바인딩 도구들. 여러 기본 뷰들과 레이아웃. 제플린이나 피그마를 보면서 아마도 수많은 화면들을 만들었고 그에 따른 여러가지 이슈를 해결해 왔을 것이다.
  • 하지만 Compose 를 도입하면서 많은 것들을 버려야할 수 있다.
  • 개발자들은 이것을 받아들일수 있을 것인가?
  • 뷰 뿐만이 아니다. 앱 구조까지 많은 부분이 고민되어야하고 변경 되어야한다.

 

3. 우리가 쳐야 되는 디자인은 머테리얼 디자인이 아니다.

  • 플러터와 마찬가지로 Compose 또한 머테리얼 디자인 테마와 위젯들을 기본으로 제공한다. 하지만 우리가 다니고 있는 회사에서는 그렇게 심플한 디자인이 나오지 않는다.
  • 그렇다. 프로덕트의 디자인은 복잡하다. 앱 개발을 하며 커스텀 뷰나 컴포넌트를 만드는일 이 꽤 많고, 이런 작업들은 사실 쉽지 않다. 그런데 컴포즈가 이런 작업을 더 쉽게 만들어주는가? → 아닌것 같다.

 

4. Android 라이프 사이클에 대한 연결이 어려움

  • Composable 안에서 Activity lifeCycle의 상태를 알수 없다.
  • 각 라이프사이클 콜백에서 라이프사이클 상태를 변경해주는 식으로 구현

 

Compose best practice for performance

 

1.Release 모드에서 R8 난독화를 사용한다.

  • 최적화를 통해서 앱을 더 빠르게 할것이다. Compose 를 사용하는 경우에도.
  • 뭔가 디버그모드에서 성능이 안나오는 숨은 버그같은게 있는건가?

 

2. Remember 함수의 사용

  • 아래 경우 항상 재실행된다. 왜냐면 우리의 소팅이 스콥 내부에 있다. 이것은 매번 recomposition 될때마다 불리게 될것이다. 리멤버 함수를 이용해서 소팅로직을 분리하면 이런 이슈를 해결할 수 있다.

 

  • remember를 사용하여 계산결과를 저장한다. 계산이 한 번 실행되고 필요할 때마다 결과를 가져온다.

 

3. 역방향 쓰기 방지

  • ‘이미 읽힌 상태에 쓰지 않는다’ 를 지킨다
@Composable
fun BadComposable() {
    var count by remember { mutableStateOf(0) }

    // Causes recomposition on click
    Button(onClick = { count++ }, Modifier.wrapContentSize()) {
        Text("Recompose")
    }

    Text("$count")
count++ // Backwards write, writing to state after it has been read
}

 

 

좋은 샘플 코드들

GitHub - android/compose-samples: Official Jetpack Compose samples.

GitHub - Gurupreet/ComposeCookBook: A Collection on all Jetpack compose UI elements, Layouts, Widgets and Demo screens to see it's potential

 

 

 

참조 :

스터디 그룹

반응형

'안드로이드' 카테고리의 다른 글

ScopeStorage 저장공간에 대한 정의  (0) 2022.11.14
Bitrise-android  (0) 2022.11.14
STT관련 라이브러리 API정보  (0) 2022.11.09
STT (구글) - 샘플코드  (0) 2022.11.09
STT(구글) - SpeechRecognizer Document  (0) 2022.11.09