Android Jetpack - Compose 개념 정리

David·2022년 7월 9일
0

[Android] Compose

목록 보기
1/5
post-thumbnail

🏁 ComposeUI 여정의 시작


ComposeUI의 발전을 조금씩 지켜 보다가
근무하는 회사에서 조금씩 ComposeUI를 적용 해보자고 해서
Compose를 적용하기 앞서 핵심 개념이 무엇인지 정리 해볼려고 한다.


⚡️ ComposeUI 핵심 특징


✅ 선언형(Declarative) 프로그래밍으로 상태를 파악하기 쉽다

  • 특정 상태에서 UI의 형태를 완전히 설명
  • 상태가 바뀌면 프레임워크에서 UI 업데이트를 처리

    뷰의 상태만 신경쓰고
    디테일한 부분은 프레임워크가 관리

✅ Composable 함수는 값 반환 대신 UI를 전달

  • Composable은 데이터를 매개변수로 받아서 UI를 전달하는 방식

✅ Compose Recomposing

  • Compose 는 Imutable 함

    따라서 상태가 바뀌거나 데이터 목록이 바뀌었을 때
    Recomposing 하게 됨

✅ 단일 데이터 방향

  • ComposeUI에서 데이터를 관찰
  • 각 구성 요소의 매개변수로 전달
  • 각 구성 요소는 필요한 상태만 수신
  • 데이터를 바꿀 때만 업데이트하면 된다.

✅ Single source of truth

  • 기존의 안드로이드 UI 시스템처럼 각각의 뷰가 상태 관리 x
    🤮 UI 상태와 <--> 데이터의 상태가 달라지는 문제
  • 데이터가 여러 곳에 존재하지 않고
    뷰에서 읽는 모든 데이터들은 하나의 원천을 가지고 상태를 관리



🚨 ComposeUI 알아야 할 사항들


📌 순서와 관계없이 실행할 수 있다.

  • 다른 구성 가능한 함수 호출이 포함되어 있다면
    그 함수는 순서와 관계없이 실행될 수 있다.
  • 일부 UI 요소가 다른 UI 요소보다
    우선순위가 높다는 것을 인식하고
    그 요소를 먼저 그리는 옵션이 있다.

📌 동시에 실행할 수 있다.

  • 다중 코어를 활용하고 화면에 없는 구성 가능한 함수를
    낮은 우선순위로 실행할 수 있다.
  • 이 최적화는 구성 가능한 함수가
    백그라운드 스레드 풀 내에서 실행될 수 있음 의미.
  • 구성 가능한 함수가 viewModel 에서 함수를 호출하면
    Compose는 동시에 여러 스레드에서 이 함수를 호출할 수 있다.
  • 구성 가능한 람다의 변수를 수정하는 코드는 피해야 한다.
    🤮 스레드로부터 안전하지 않고 람다의 허용되지 않는 부작용 때문
@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
    var items = 0

    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column { // 람다 안에 변수를 수정하는 코드
            for (item in myList) {
                Text("Item: $item")
                items++ // Avoid! Side-effect of the column recomposing.
            }
        }
        Text("Count: $items")
    }
}

📌 최대한 많은 수의 함수 및 람다를 건너 뛴다.

  • Composable 에서 recompose 할 때는
    넘겨받는 파라미터가 변경될 때recompose 함
  • 해당 파라미터가 변경이 되지 않았다면 recompose 건너뜀
/**
 * 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
	    // header가 변경 되었을 때만 Text recompose 
        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) }))
}

📌 낙관적이며 취소될 수 있다.

  • 낙관적 > 매개 변수가 다시 변경되기 전에 재구성을 완료할 것을 예상한다.
  • 재구성이 완료되기 전에 매개변수가 변경되면 Compose는 재구성을 취소하고
    새 매개변수를 사용하여 재구성을 다시 시작할 수 있다.

📌 애니메이션의 모든 프레임에서와 같은 빈도로 매우 자주 실행될 수 있다.

  • 함수가 기기 저장소에서
    읽기와 같은 비용이 많이 드는 작업 실행하면
    함수로 인해 UI 버벅거림 발생할 수 있다.

  • 위젯이 기기 설정을 읽으려고 하면 잠재적으로 이 설정을
    초당 수백 번 읽을 수 있고 앱 성능에 치명적인 영향

  • 구성 가능한 함수에
    데이터가 필요하다면 데이터의 매개변수를 정의해야 한다.

  • 그런 다음, 비용이 많이 드는 작업을 구성 여부의 다른 스레드로 이동하고
    mutableStateOf 또는 LiveData를 사용하여
    Compose에 데이터를 전달할 수 있다.



👏🏻 1장을 마무리하며...


ComposeUI 내용을 최대한 필요하고 핵심적인 내용으로
작성 해보았는데 쉽지 않았습니다 🤣

해당 컨텐츠가 도움이 되길 바라며
수정 & 보충이 필요한 부분이 있다면 (그 외 어떤 것도)
댓글 달아주시면 피드백 내용을 보강하여

Compose를 시작하는
많은 개발자에게 도움이 되는 컨텐츠를 제공하고 싶네요 🙇🏻

profile
공부하는 개발자

0개의 댓글