프로그래밍/Android

[Jetpack Compose] 왜 Jetpack Compose가 나와야만 했을까?

Lou Park 2021. 8. 30. 23:57

Jetpack Compose를 눈여겨 본지 1년정도 된 것같다. 오랫동안 xml로 레이아웃을 구성하면서 큰 불편함이 없어서인지, (불편함에 길들여졌었겠지) 이 새로운 기술이 정착될지, 도태될지 지켜보기만하고 실제로 시도해보지는 않았다. 원래는 Android Studio Preview에서만 지원되었으나 이제는 정식 지원하게 되었다. 내가 Jetpack Compose와 마주할때가 된 것 같다.

 

Seperation of concerns

xml을 사용하는 UI 디자인 방식에 무슨 문제가 있길래 Jetpack Compose가 등장했을까? 그것이 가장 궁금했다.

SoC(관심사의 분리, Seperation of concerns) 원칙에 대해 들어봤을 것이다. 우리 프로그램은 하나의 거대한 시스템이고, 처리해야할 부분이 매우 많다. 이를 모듈로 잘게 쪼개서 각자 본인의 일을 하도록하면 시스템도 잘 동작할것이다. 따라서 프로그래밍을 할때 모듈간 의존도를 낮추고, 내부 응집력을 높이는 것이 유지보수 측면에서도, 기능적인 측면에서도 좋다. 

 

ViewModel과 layout.xml의 관계를 생각 해보자. ViewModel은 화면을 구성하는데 필요한 데이터를 layout에 전달한다. 그냥 전달만 해서는 안된다. findViewById를 사용해서 xml에 정의한 ID를 통해 View를 직접 지정해주어야 한다. 당연하다고 생각 했지만, 바로 여기에서 모듈간 의존도가 생긴다. xml이 어떻게 생겼는지, 어떤 ID가 무슨 View인지 알아야한다. ViewModel과 xml이 긴밀하게 연결되어있음에도, xml과 kotlin(혹은 Java)이라는 다른 언어를 사용하였기 때문에 응집력을 높일 수도 없다. Jetpack Compose의 등장 전 이러한 문제들을 해결하려 했던 시도가 ViewBinding이라고 생각한다.

 

 

구글 공식 문서에서 본 Jepack Compose를 채택하는 이유

코드 감소 -  모든 것이 같은 언어로, 가끔은 같은 파일에서 작성되어 추적하기가 쉬워져 유지보수가 용이하다.

직관적 - 선언적 API를 사용하기 때문에. 

빠른 개발 속도 - 기존 코드와 호환된다. 그리고 @Preview를 통해 앱을 빌드하지 않고도 만들어진 UI와 상호작용할 수 있다.

 

 

선언형 UI (Declarative UI)

안 읽은 메일의 수에 따라 다른 UI

기존의 명령형 UI(Imperative)와는 다른 개념이다. 새로운 UI 패러다임이라고 불러야하나!

위 그림처럼 안 읽은 메일의 갯수에따라 다르게 표시 해줘야하는 UI가 있다고 할때, 명령형 UI식으로는 이렇게 코딩을 한다. (물론 예시코드가 좀... 구리지만 비교를 위하여~) "어떤 조건이되면 어떻게 하라"고 상술을 해주는거다.

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을 이용하면 이렇게 표현할 수 있다.  뷰가 속성 중심적이게 되고, 더욱 더 멍청해지는거다. 아주 좋은 현상이다! React는 아주 예전부터, Flutter나 Swift UI 역시 이러한 선언형 UI 패러다임을 따라가고 있다.

@Composable
fun BadgedEnvelope(count: Int) {
  Envelope(fire=count > 99, paper=count > 0) {
    if (count > 0) {
      Badge(text="$count")
    }
  }
}

 

글을 작성하면서 Jetpack Compose를 도입해야하는 이유에 대해 나 스스로 많이 설득이 된 것 같다. 다음 글 부터는 짬짬히 Jetpack Compose 대략적인 강의와 하위 호환법들을 적어보려한다. 부지런함이 필요하지만...

 

 

참고자료

https://medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050

https://developer.android.com/jetpack/compose/why-adopt