ABOUT ME

-

  • 핵심만 골라 배우는 젯팩 컴포즈 Study 2주차
    Android 2023. 1. 25. 20:56


    Chapter 18 ~ 26

     

    컴포즈 개요

    • 컴포즈는 앱 개발에 관한 완전히 새로운 접근 방식.
    • 선언적인 동시에 데이터 주도적.

    컴포즈의 선언적 구문

    • 선언한 레이아웃 배치, 제한, 렌더링 방법에 관한 모든 복잡한 세부 사항은 컴포즈가 자동으로 처리.
    • 계층적으로 구조화되어 있기 때문에, 재사용 가능한 서브 뷰를 조합함으로써 복잡한 뷰를 쉽게 만들 수 있음.

    명령형 프로그래밍 패러다임

    • 기존의 명령형 패러다임은 트리형태로 뷰를 구성. 레이아웃 위에 텍스트 뷰, 버튼 등을 쌓아 뷰를 그림.
    • UI를 업데이트 하기 위해 일반적으로 findViewById() 같은 함수로 트리를 탐색해 내부 상태를 변경함.
    • xml을 inflating 하여 객체를 만들어 사용, 위젯들은 내부에 각각 상태를 가짐. 상태에 접근할 수 있는 게터, 세터 제공.
    • 수동으로 작업하는 기존 방법은 오류가 발생할 가능성 큼.

    선언형 프로그래밍 패러다임

    • 선언형 UI 모델은 필요한 변경사항만 적용하는 방식.
    • 특정 시점에 UI의 어떤 부분을 다시 그려야 하는지를 지능적으로 선택.
    • Compose compiler가 어떤 시점에 어떤 부분을 그려야 하는지 판단해 업데이트 함.
    • 게터, 세터 존재하지 않음. 동일한 composable function을 다른 param으로 호출해 UI를 변경.

    컴포즈는 데이터 주도적

    • 컴포즈는 상태 기반 시스템으로 데이터를 상태로 저장해 데이터의 변경을 감지하기 위한 코드를 추가로 작성하지 않아도, 변경사항이 사용자 인터페이스에 자동으로 반영.
    • 상태가 변경되면 해당 데이터를 구독하는 컴포넌트가 삭제되고 새로운 컴포넌트가 생성되어 상태를 반영, 이 과정을 재구성이라 함.
    • 컴포즈는 데이터 변경에 기반해 앱의 동작과 형태를 결정한다는 점에서 데이터 주도적이라 함. 상태 재구성을 통해 이를 달성.

    컴포저블 함수

    • 컴포저블 함수는 컴포즈로 사용자 인터페이스를 만들기 위해 이용하는 특수한 코틀린 함수.
    • @Composable 어노테이션을 이용해 선언, 코틀린의 일반 함수와 구별.
    • 본질적으로 컴포저블 함수는 데이터를 사용자 인터페이스 요소로 변환.
    • 컴포즈 런타임으로 사용자 인터페이스 요소를 전달하면 컴포즈 런타임을 통해 렌더링.
    • 분리 및 재사용을 위해 가능한 최소한의 정보를 포함해야함.

    상태 컴포저블, 비상태 컴포저블

    • 상태란 앱 실행 중 변경할 수 있는 모든 값.
    • 컴포저블 함수는 상탯값 저장 여부에 따라 상태 컴포저블 비상태 컴포저블로 분류.
    • 상태를 저장하려면 remember 키워드와 mutableStateOf 함수 호출.
    • remember는 객체를 컴포지션에 저장, remember를 호출한 컴포저블이 컴포지션에서 삭제되면 그 객체를 삭제.
    • mutableStateOf는 컴포즈에서 관찰 가능한 MutableState를 만듬. 관련 값이 변경되면 그 값을 읽는 컴포저블 함수의 재구성이 예약됨.
    • 스스로 상탯값을 저장하지 않는다면 비상태 컴포저블.

    파운데이션 컴포저블, 머터리얼 컴포저블

    • 컴포즈에서 번들로 제공하는 컴포저블은 레이아웃, 파운데이션, 머터리얼 디자인 이 세 가지로 분류.
    • 레이아웃 컴포넌트 : 컴포넌트를 화면에 배치, 상호 동작하는 방법을 정의.
      • Box, ConstaintLayout, BoxWithConstraints, Row, Column
    • 파운데이션 컴포넌트 : 기본적인 사용자 인터페이스 기능을 제공하는 최소한의 컴포넌트 집합.
      • BaseTextField, LazyRow, Canvas, Shape, Text, Image, LazyColumn
    • 머터리얼 디자인 컴포넌트 : 구글이 제공하는 머터리얼 테마 가이드라인을 만족하는 컴포넌트.
      • AlertDialog, RadioButton, Button, Card, CheckBox, Snackbar..

    컴포즈 상태

    • 컴포저블 함수에서 상태 변수에 할당된 값은 기억되어야 함.
    • 상태를 포함한 컴포저블 함수를 호출할 때마다 지난번에 호출했을 때의 상탯값을 기억해야 함.
    • 상태 변수의 변경은 사용자 인터페이스를 구성하는 컴포저블 함수 계층 트리 전체에 영향을 미침.

    컴포즈 재구성

    • 재구성은 컴포저블 함수의 계층 안에서 상탯값이 변경될 때 일어남.
    • 해당 함수들을 다시 호출하고, 새로운 상탯값을 전달하는 것.
    • 전체 컴포저블 트리를 재구성하는 것은 비효율적.
    • 상태 변화에 직접 영향을 받는 함수들만 재구성하는 지능적 재구성을 이용.

    단방향 데이터 흐름

    • 컴포저블은 상태 및 이벤트를 기반으로 작동
    • 한 컴포저블에 저장된 상태는 자식 컴포저블 함수들에 의해 직접 변경되어서는 안됨.
    • 데이터는 컴포저블 계층을 따라 전달되며, 이벤트는 계층의 반대 방향인 조상 컴포넌트의 핸들러로 호출됨.

    상태 호이스팅

    • 상태를 자식 컴포저블에서 이를 호출한 부모 컴포저블로 들어 올림.
    • 상태를 부모 함수로 들어 올림으로써 재사용성 용이.
    • 함수에 상태를 추가할 때는 호출자에게 상태를 호이스팅 가능한지를 고려하자.

    환경 설정 변경을 통한 상태 저장

    • remember 키워드는 configuration change에서 상태를 유지하지 못함.
    • remeberSaveable을 이용해 유지.

    CompositionLocal

    • 컴포저블 계층 트리 상위에서 선언된 상태를 계층 트리 하위의 함수에서 이용하는 방법 제공.
    • 해당 상태가 선언된 함수와 상태를 이용하는 함수 사이에 있는 모든 컴포저블에 상태를 전달하지는 않음.
    • 트리의 깊이가 깊을수록 여러 단계의 컴포저블에 상태를 전달해야 하는데, CompositionLocal을 통해 중간 노드에 상태를 전달하지 않고도 하위 노드에서 이용 가능.
    • CompositionLocal을 이용해 상태를 저장하려면 ProvidableCompositionLocal 인스턴스를 생성해야 함.
      • compositionLocalOf() 혹은 staticCompositionLocalOf() 함수를 호출해 얻을 수 있음.
      • staticCompositionLocalOf() : 자주 변경되지 않는 상탯값을 저장할 때 이용. 상탯값이 변경되면 해당 상태가 할당된 노드의 하위 노드를 모두 재구성해야 하기 때문.
      • compositionLocalOf() : 현재 상태에 접근하는 컴포저블에 대해서만 재구성을 수행. 변경이 잦은 상태를 다룰 때 이용.
    • 이런 방식으로 선언된 상태는 해당 값이 할당된 계층 트리의 브랜치에만 영향을 줌.

    Slot API

    • 어떤 컴포저블을 호출 시점에 동적으로 지정 가능.
    • 컴포저블이 호출될 때 파라미터로 전달되며, 컴포즈 런타임 시스템이 사용자 인터페이스를 렌더링할 때 포함.
    • Unit 객체를 반환하도록 선언되어 있음.
    @Composable
    fun SlotDemo(middleContent: @Composable () -> Unit) {
    

    모디파이어

    • Modifier 객체를 기반으로 구현.
    • 이를 이용해 테두리, 패딩, 배경, 크기, 이벤트 핸들러, 제스처 등 다양한 프로퍼티 설정 가능.
    • 다른 컴포저블에 전달해 형태나 행동을 변경할 수 있음.
    • 모디파이어 연결 순서는 결과에 영향을 미침.

    컴포저블에 모디파이어 지원 추가

    • 첫 번째 규칙은 파라미터 이름이 modifier이고 함수의 파라미터 리스트 중 두 번째 선택적 파라미터여야 함.
    • 모디파이어 파라미터는 반드시 선택적이어야 하며, 해당 함수는 모디파이어 없이도 호출할 수 있어야 함.

    모디파이어 조합

    • 동일한 컴포저블에 적용되는 둘 이상의 Modifier 객체를 이용할 때 then 키워드 이용해 모디파이어들을 조합.
    • val combinedModifier = firstModifier.then(secondModifier)..

    Row 컴포저블

    • 자식 컴포넌트를 화면의 수평 방향으로 배열.

    Column 컴포저블

    • 자식 컴포넌트를 화면의 수직 방향으로 배열.

    레이아웃 배열 간격 조정

    • Arrangement.SpaceEvenly : 자식들을 균일한 간격을 유지. 첫 번째 자식의 앞, 마지막 자식의 뒤 공간 포함.
    • Arrangement.SpaceBetween : 자식들을 균일한 간격을 유지. 첫 번째 자식의 앞, 마지막 자식의 뒤 공안을 포함 안함.
    • Arrangement.SpaceAround : 자식들을 균일한 간격을 유지. 첫 번째 자식의 앞, 마지막 자식의 뒤 공간은 각 자식들 사이 공간의 절반.

    Box 레이아웃

    • 자식들을 호출한 순서에 따라 위로 쌓아서 정렬.
    • 첫 번째로 호출된 자식은 스택의 가장 아래에 위치.
    • 기본적으로 콘텐츠 영역의 왼쪽 위 모서리 기준으로 위치.

    clip() 모디파이어

    • 컴포저블을 특정한 형태로 렌더링 가능.
    • CircleShape, RoundedCornerShape, CutCornerShape 등을 호출해 형태 변경 가능.

    Q) 컴포즈 프리뷰를 보기 위해서는 반드시 빌드를 거쳐야한다. 빌드가 오래 걸리는 큰 프로젝트에서 컴포즈를 어떻게 활용하면 좋을까?

    • 모듈화를 시켜 빌드 시간을 조금이라도 줄인다.
    • 디버깅은 할 수 없겠지만, R8을 이용한 릴리스 모드로 빌드를 해본다.

     

    반응형

    댓글

Designed by Me.