본문 바로가기
프로그래밍/Jetpack Compose

[Jetpack Compose] 1분만에 Jetpack Compose 에 대해서 간단히 알아보자 !

by dev_gyu 2024. 9. 23.
728x90

# Jetpack Compose 란?

  • Kotlin 으로 제작되는 라이브러리이며 선언형 UI 구성 방식이다
  • 기존 안드로이드 작업의 경우 명령형 UI 구성 방식인 Xml 에서 코드 작성 후 class 에서 코드를 재작성하는 방식으로 운영되다 보니 보일러 플레이트 코드가 생성되고 불필요한 작업이 진행되었다.
  • 뷰를 구성할 때 기존에는 트리 탐색 방식으로 구현하던 것처럼 복잡하였지만, 현재는 내부 속성을 변경하는 식으로 사용할 수 있어서 더욱 간편하고 직관적으로 코드를 짤 수 있게 되었다.
  • 추가적으로 가장 좋은 부분은 Preview 를 통하여 개발 실시간으로 현재 UI 가 어떻게 개발되어가는지 확인이 가능하다.

 

# Jetpack Compose 의 라이프사이클

Compose Lifecycle 의 경우 Activity, Fragment Lifecycle 과는 달리 매우 간단한 사이클을 가진다.

 

1. Composition 시작

2. 0번 이상의 재구성 (Recomposition)

3. Composition 종료

 

위의 세 가지 사이클로 이루어져있다.

# 사용 방법?

XML 을 사용중인 경우

  1. Compose 라이브러리들을 dependencies 에 추가해준다
  2. UI 를 그리는 모듈 build.gradle.kts 에 아래 코드를 추가해준다.
buildFeatures { compose = true }

 

새롭게 프로젝트를 만드는 경우

  1. Empty Activity 를 선택 시 아래와 같은 코드가 깔리게 된다.
  2. setContent 내부에 컴포넌트를 구현하여 사용한다.

 

setContent - 앱의 기본 UI를 정의하는데 사용되는 함수, 이곳 내부에 @Composable Annotation 을 사용한 Composable 를 연결해서 그리고 렌더링 할 수 있다.

@Preview - Jetpack Compose에서 UI 미리보기를 생성하는 데 사용된다.

@Composable - 함수가 Jetpack Compose에서 사용되는 Composable 함수임을 나타낸다.

 

연습이 필요한경우 아래 안드로이드에서 제공하는 Compose Basics 를 이용하면 튜토리얼을 할 수 있습니다 :)

https://developer.android.com/codelabs/jetpack-compose-basics#0

 

# Remember 란?

이러한 Jetpack Compose 에서는 변수를 선언할 때 리컴포지션이라는 특성과 함께 상태 관리를 위해 remember 라는 특별한 방식을 사용한다

아래를 참조하면 좋음

https://developer.android.com/develop/ui/compose/state

 

기존 xml 을 사용할 때는 UI 를 그릴 때 리컴포지션이라는 단계 없이 진행이 되었다면, 현재 Compose 에서는 Recomposition 이라는 것이 생겼기 때문에 remember 의 사용은 필수나 다름없다

 

하나 예를 들어보자

@Composable
fun test(number: Int){
    var a = 0
    Text(text = number)
    Button(onClick = { a++ }){}
}

 

위와 같은 함수가 존재할 때 Button 을 클릭하면 a 는 onClick 에 설정된 값에 따라 1씩 증가한다.

하지만 number 의 값이 바뀌거나, 앱의 구조가 바뀌는 등의 상황으로 인해 컴포넌트가 리컴포지션이 되는 상황이 발생하게 된다면, a 는 다시 0으로 초기화되어버린다.

 

우리는 이러한 리컴포지션에 대응하기 위해 remember 를 사용하여 객체의 값을 캐싱하고, 상태를 유지하는 것이다.

그렇다면 다시 한 번 아래 코드로 바꿔보도록 하자

@Composable
fun test(){
    var a = remember { 0 }
    Text(text = a.toString)
    Button(onClick = { a++ }){}
}

 

만약 이 상태에서 Button 을 누르게 된다면 Text 의 값이 바뀔까?

답은 그렇지 않다 이다.

이유는 각 컴포넌트들은 상태의 변화에 따라 리컴포지션이 되는데, 변수 a 는 상태가 아니기 때문에 값의 변화를 컴포넌트들이 감지하기 못하기 때문이다.

 

Button 을 클릭함에 따라 Text 의 값을 바꿔주고 싶다면 다음과 같이 바꿔주도록 하자

 

// 1번째 방식
@Composable
fun test(){
    var a by remember { mutableStateOf(0) } // Int 로 return 된다.
    Text(text = a.toString)
    Button(onClick = { a++ }){}
}

// 2번째 방식
@Composable
fun test(){
    var a = remember { mutableStateOf(0) } // MutableState 로 return 된다.
    Text(text = a.value.toString)
    Button(onClick = { a++ }){}
}


// 3번째 방식
@Composable
fun test(){
    var a by remember { mutableIntStateOf(0) } // Int 로 return 된다.
    Text(text = a.value.toString)
    Button(onClick = { a++ }){}
}

// 4번째 방식
@Composable
fun test(){
    var a = remember { mutableIntStateOf(0) } // MutableState 로 return 된다.
    Text(text = a.value.toString)
    Button(onClick = { a++ }){}
}

 

4가지 방식이 존재하는데, 이것들의 차이를 알려주자면

  1. mutableStateOf 와 mutableIntStateOf 의 차이점은 컴포즈 컴파일러가 Auto Casting 을 해주는 것과 개발자가 직접 타입을 지정해 사용해주는 것의 차이
  2. = (equals) 와 by 의 차이점은 MutableState 로 return 되느냐, State.value 로 return 되느냐 차이다. (하지만 개인적으로 상태 호이스팅과 .value 를 통한 값 직접참조, val 이어도 값의 수정이 된다는 점 때문에 by 를 주로 사용한다)

rememberSaveable 은 뭐지?

위의 remember 가 단순히 캐싱을 한다면, rememberSaveable 은 Bundle 객체에 데이터를 저장하는 방식이다.

remember 의 경우 앱의 구조가 변경되는 경우 캐싱되었던 데이터가 모두 날아가지만 rememberSaveable 은 번들에 저장하므로 데이터가 보존된다.

 

rememberSaveable 의 경우 일반적으로는 원시 타입만 저장이 되며, 따로 클래스 같은 것을 저장하고 싶은 경우 Saver 를 통해 커스텀 하는 경우 저장이 가능해진다.

728x90