ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (기초) 1-1. Jetpack Compose : 기존 View 시스템과의 차이
    안드로이드 학습/Compose 2025. 9. 9. 17:27

    기존에 안드로이드의 View 시스템은 XML 파일을 이용해서 UI를 표현하였습니다.


    🧱 XML 레이아웃이란?

    • XML은 "eXtensible Markup Language"의 약자로, 데이터를 구조화하여 표현하는 언어입니다. 안드로이드에서는 XML을 사용하여 앱의 화면(UI)을 구성합니다. 

     

    📐 XML 레이아웃 구조

     

    안드로이드 앱의 화면은 **뷰(View)**와 **뷰 그룹(ViewGroup)**으로 구성됩니다.

    • 뷰(View): 버튼, 텍스트, 이미지 등 화면에 표시되는 개별 요소입니다.
    • 뷰 그룹(ViewGroup): 여러 뷰를 포함하고 배치하는 역할을 합니다. 예를 들어, LinearLayout은 뷰를 세로 또는 가로로 나열하는 뷰 그룹입니다.

     

     

    안드로이드 앱에서 UI를 만들 때, **기존 방식(View 시스템)**은 크게 세 가지 단계로 이루어집니다.

     

    1) XML 파일에서 UI 정의

    2) Activity/Fragment에서 XML 로드

    3) 코드에서 UI 요소 참조 후 동작 구현

     

    이러한 기존 방법은 몇가지 문제점들이 있습니다.

     

    • 상태 관리가 번거로움
      • UI 상태가 바뀔 때마다 직접 코드로 갱신
      • ListView/RecyclerView 등 복잡한 데이터 연결 시 Adapter 필요
    • 코드/레이아웃 분리
      • UI(XML)와 동작(Activity or Fragment)이 여러 파일에 나뉘어 유지보수 어려움
    • 뷰 계층 구조가 깊어지면 성능 저하
      • LinearLayout, RelativeLayout 중첩 → measure/layout 비용 증가
    • 재사용성 낮음
      • CustomView 만들거나 XML include/merge 활용해야 함

     

    뷰 계층 구조가 깊어지면 성능 저하 추가 설명 : 

    더보기
    더보기

    Compose는 뷰 계층이 깊어지면 성능에 영향은 있지만 View 시스템보다 계층 최적화에 유리한 구조라서 체감의 차이가 있따. 

     

    View 시스템 (XML 기반) :

    • 전통적인 View 계층은 트리 구조로 되어 있음.
    • ViewGroup은 자식 뷰들을 measure > layout > draw 하는 과정을 거침
    • LinearLayout, RelativeLayout 중첩이 많아지면 measure/layout 연산 비용이 기하급수적으로 늘어남.
    • 그래서 ConstraintLayout 같은 Flat 구조 권장

    Compose (Declarative UI)

    • Compose도 내부적으로 UI Tree(Composable Tree)를 가짐.
    • 하지만 Compose는 Recomposition + Slot Table 구조 덕분에 차이가 있음.
      • 변경된 State와 관련된 부분만 다시 계산 (전체 UI를 다시 그리지 않음)
      • Layout 계산도 최소화
      • Modifier 체인은 여러 뷰를 중첩하는 게 아니라 데코레이터 패턴처럼 연결되어 있어, 실제 계층 깊이가 ViewGroup 중첩보다 훨씬 얕음.

     

    Compose

    Jetpack Compose는 안드로이드의 최신 UI 툴킷으로, 선언형(Declarative) 방식으로 UI를 구축할 수 있게 해줍니다. 이는 기존의 XML 기반 UI 개발 방식에 비해 많은 장점을 제공합니다.

     

     

    Jetpack Compose 장점

    1. 📉 코드량 감소 및 유지보수 용이
      • 간결한 코드: XML 없이 Kotlin만으로 UI 작성 가능 → 코드가 크게 줄어듭니다.
      • 유지보수 편리: 코드 구조가 단순하고 직관적이어서 관리가 쉬움.
      • 버그 감소: 불필요한 코드와 중복이 줄어 오류 발생 가능성 감소.
      • 예시: Twitter(버튼 코드 10배 감소), Monzo(RecyclerView 화면 코드량 대폭 축소).
    2. 직관적인 UI 개발
      • 선언형 API: 상태에 따라 UI가 자동으로 갱신 → 로직 단순화.
      • 컴포넌트화: 작은 단위로 분리 가능해 재사용성과 테스트가 용이.
      • 명확한 상태 관리: 단일 소스로 UI와 로직이 분리되어 흐름이 명확.
      • 예시: Twitter(테마 설정 직관적), Cuvva(상태 관리 명확).
    3. 🚀 개발 속도 향상
      • 점진적 전환 가능: 기존 View 시스템과 호환 → 필요한 부분만 Compose로 교체 가능.
      • 기존 라이브러리와 연동: Navigation, ViewModel, Coroutines 등과 자연스럽게 사용 가능.
      • 실시간 미리보기: Android Studio Preview로 UI 상태를 빠르게 확인 및 테스트 가능.
      • 예시: Cuvva(View와 Compose 혼용도 문제 없음), Square(다양한 UI 상태 미리보기 활용).
    4. 🎨 강력한 기능 제공
      • 플랫폼 API 연동: 안드로이드 API와 직접 연결 가능.
      • UI 기능 내장: Material Design, 다크 모드, 애니메이션 기본 지원.
      • 유연한 확장성: 자체 디자인 시스템도 쉽게 적용 가능.
      • 예시: Monzo(애니메이션 손쉬운 적용), Square(자체 디자인 시스템 활용).

     

    항목 기존 View 시스템 Jetpack Compose
    UI 정의 명령형, XML + Kotlin 선언형, Kotlin 코드만
    코드 양 많음, 보일러플레이트 필요 적음, 간결
    테스트 Espresso 등 별도 도구 필요 Compose Preview, 단위 테스트 쉬움

     

     

    명령형 프로그래밍과 선언형 프로그래밍 

     

    • 명령형 (Imperative)
      • "UI가 어떻게 변해야 하는지"를 단계별로 직접 지시.
      • 개발자가 UI 업데이트 과정을 일일이 관리해야 함.
      • 기존 Android View 시스템 방식.
    • 선언형 (Declarative)
      • "UI가 어떤 상태여야 하는지"만 선언.
      • UI는 상태(State)에 따라 자동으로 갱신됨.
      • Jetpack Compose, React 같은 방식.

     

    1. 명령형 (기존 View, Imperative)

    <!-- xxx.xml -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hi" />
    
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click" />

     

    // xxx.kt
    val textView = findViewById<TextView>(R.id.textView)
    val button = findViewById<Button>(R.id.button)
    
    button.setOnClickListener {
        textView.text = "Hello"   // 직접 UI 업데이트
    }

     

    2. 선언형 (Compose, Declarative)

    @Composable
    fun Greeting() {
        var text by remember { mutableStateOf("Hi") }
    
        Column {
            Text(text) // 상태에 따라 자동 갱신
            Button(onClick = { text = "Hello" }) {
                Text("Click")
            }
        }
    }

     

    핵심 차이

    • 명령형: "버튼 클릭 시 → TextView의 텍스트를 바꿔라" (행동 하나하나를 지시)
    • 선언형: "text 상태가 바뀌면 → Text UI는 알아서 갱신" (최종 결과만 선언)
Designed by Tistory.