본문 바로가기

안드로이드/JetPack

[Android] Jetpack Compose 개요

Jetpack Compose

Google에서 발표한 Jetpack 중 Compose는 안드로이드 UI를 XML이 아닌 선언형으로 개발할 수 있는 라이브러리이다. 더 적은 코드와 직관적인 사용법으로 UI 개발이 쉬워진다.

 

Compose를 통해 해결할 수 있는 것

관심사의 분리는 유명한 소프트웨어 디자인 원칙이다. 이를 이해하기 위해선 "결합도(Coupling)"와 "응집도(Cohesion)"을 이해해야 한다. 결합도는 서로 다른 모듈의 유닛 간의 종속성을 의미한다. 응집도는 모듈 내의 유닛 간의 그룹화의 정도를 나타낸다. 유지보수가 쉬운 소프트웨어를 개발하기 위해선 결합도를 낮추고, 응집도를 높혀야 한다.

 

현대 안드로이드 개발 패턴은 ViewModel을 사용하고 Layout(XML)에서 ViewModel의 데이터를 관찰하는 것이다. 중요한 점은 ViewModel과 Layout은 결합도가 높다는 것이다. 그리고, 대부분의 최신 앱은 UI를 동적으로 표시하고 실행 중에 변화한다. 

지금까지 ViewModel은 Kotlin, Java로 작성되고, Layout은 XML로 작성된다. 이런 언어 차이로 인해 ViewModel과 Layout이 밀접하게 관련이 있을 때도 언어라는 장벽에 의해 강제적으로 분리되어 작성하게 된다.

 

Compose를 활용하면 ViewModel과 Layout을 모두 Kotlin으로 작성하여 이러한 문제를 해결할 수 있다. 같은 언어로 작성하면서 이전엔 암시적이었던 종속성이 좀 더 명시적으로 바뀐다. 또한, 결합을 줄이고 응집력을 높이는 방향으로 개선할 수 있다.

 

일부 프로그래머는 이를 Logic과 UI가 혼합된다고 생각할 수도 있다. 하지만 현실은 어떤 구조로든 App에 UI 관련 Logic이 있다는 것이다. 프레임워크 자체는 이를 변경할 수 없다.

 

하지만, 프레임워크가 가능한 것은 분리를 쉽게 도와주는 것이다. 그게 바로 Composable 함수이다. 함수는 관심사를 분리하기 위한 대표적인 방식이다. 이를 Composable에 적용하여 유지 보수가 가능하며 깨끗한 코드를 작성할 수 있게 도와준다.

 

선언형 UI

Compose는 UI를 명령형이 아닌 선언형으로 작성할 수 있게 한다. 읽지 않은 메시지 아이콘이 있는 이메일 앱을 개발한다고 가정하자. 메시지가 없을 떄는 빈 봉투가 렌더링되고, 읽지 않은 메시지가 존재할 때는 봉투와 함께 읽지 않은 메시지의 수를 보여준다. 만약, 100개 이상일 경우 불꽃 이미지를 포함하여 렌더링한다.

 

명령형 인터페이스를 사용하면 다음과 같은 update() 함수를 작성해야 한다.

fun updateCount(count: Int) {
  if (count > 0 && !hasBadge()) {
    addBadge()
  } else if (count == 0 && hasBadge()) {
    removeBadge()
  }
  if (count > 99 && !hasFire()) {
    addFire()
    setBadgeText("99+")
  } else if (count <= 99 && hasFire()) {
    removeFire()
  }
  if (count > 0 && !hasPaper()) {
   addPaper()
  } else if (count == 0 && hasPaper()) {
   removePaper()
  }
  if (count <= 99) {
    setBadgeText("$count")
  }
}

이 코드는 새 카운트를 수신하면 해당 상태를 반영하도록 현재 UI를 갱신하는 방법을 파악해야 한다. 이 과정에서 많은 경우가 존재하고 복잡하다.

 

만약, 선언형 UI를 사용하면 어떻게 바뀔까?

@Composable
fun BadgedEnvelope(count: Int) {
  Envelope(fire=count > 99, paper=count > 0) {
    if (count > 0) {
      Badge(text="$count")
    }
  }
}
  • count가 99를 초과하면 불꽃을 렌더링
  • count가 0을 초과하면 숫자를 렌더링
  • count가 0이면 빈 봉투만 렌더링

이것이 선언형 API가 의미하는 바이다. 원하는 대로 UI를 작성하는 과정에서 해당 상태로 전환하는 과정은 설명하지 않는다. 여기서 중요한 점은 더 이상 UI를 작성할 때 이전 상태를 고려할 필요가 없다는 것이고, 현재 상태만 고려하면 된다는 점이다.

 

 

Compose의 장단점

장점

  • 유지보수가 쉬운 깨끗한 코드를 작성할 수 있게 된다.
  • 개발이 가속화 된다. 적은 코드와 Composable 미리보기 기능
  • 직관적이다. UI 코드만 작성하면 상태에 따른 변경은 Compose가 처리한다.
  • Android 플랫폼 API에 직접 접근한다. Material Design, 다크 모드, 애니메이션 등을 지원

 

단점

  • Kotlin 버전과 Compose 버전은 매우 종속도가 높다. ex) Kotlin 컴파일러 버전이 1.5.10이면, Compose는 1.0.0만 사용이 가능함.
  • 새로운 API 학습 필요

 

출처