티스토리 뷰

Compose 특강 1회차 정리

 

Compose

 

Compose란?

안드로이드 UI를 선언적으로 구축하는 도구로 XML과 Kotlin을 사용하는
기존 View방식으로 발생하는 다양한 문제 해결을 위해 등장하였다.

 

 

View의 문제점

View는 복잡한 UI를 다룰시 관리가 어렵고 XML과 Kotlin 요소간의

밀접한 로직 결합으로 인해 가독성과 재사용성이 떨어진다는 단점이 있다.

 

그래서 CustomView 클래스를 만들어 UI 요소들이 이를 상속받도록 설계한다.

그러나 이 방법도 새로운 UI 요구사항이 발생할 때마다 CustomView 클래스를

수정해야해서 유지보수가 어려워지고 코드의 복잡성이 늘어난다는 문제가 있다.

 

 

Compose의 역할

이러한 문제를 해결하기 위해 Compose는 Kotlin 파일에서 선언적으로 UI를 작성하고,

상속 대신 합성을 채택해 UI 개발의 복잡성을 줄이고 유지보수성을 향상시킨다.

 

 

 

선언형 UI

 

Compose의 특징

Compose는 선언형(Declarative) UI 프레임워크이다.

구현의 세부 사항은 시스템이나 프레임워크에 위임하는 방식이며,

컴포저블(composable) 함수라는 독립적인 단위로 UI를 구성한다.

 

 

ViewModel의 활용

Compose 방식에서 위젯들이 Stateless 상태로 동작한다.

이는 위젯이 필요한 상태를 외부에서 전달받아 UI를 업데이트한다는 의미이다.

또한 Compose 위젯은 setter 또는 getter 함수를 노출하지 않는다.

 

View 시스템에서는 위젯이 객체로 표현된다.

그러나 Compose에서는 위젯이 객체로 표현되지 않으며,

동일한 컴포저블 함수를 다른 인수로 호출하여 UI를 업데이트한다.

 

Compose 방식을 활용하면 ViewModel 같은

아키텍처 패턴을 통해 상태를 쉽게 관리할 있습니다.

 

 

Data 흐름

 

Compose에서는 데이터가 위에서 아래로 흐르는 방식을 따른다.

상위 컴포저블이 상태를 관리하고, 그 상태를 자식 컴포저블에 전달한다.

 

 

Event 흐름

 

Compose에서는 데이터가 아래에서 위로 흐르는 방식을 따른다.

 

하위 위젯에서 발생하는 동작이나 이벤트는

상위 컴포저블이나 ViewModel에서 처리하도록 설계된다.

 

 

 

MVVM 디자인 패턴

 

MVVM이란?

Model, View, ViewModel을 활용하는 디자인 패턴을 의미한다.

 

 

각 구성요소의 역할

Model (Data Layer)

- ViewModel에서 데이터 처리를 담당
- Local DB(SQLite, Room), Network 통신(Retrofit)을 이용함

View (UI Layer)

- Activity, Fragment가 View에 해당함
- 옵저버를 통해 ViewModel의 데이터를 관찰함
- 사용자의 Action을 감지하고 데이터 변화를 통해 UI 갱신 처리

ViewModel (UI Layer)

- 사용자의 View에서 발생시키는 이벤트를 Model에 전달
- View에서 요청한 데이터 및 비지니스 로직을 LifeCycle을 이용해 처리

 

동작방식

 

UI Layer의 역할은 화면에 애플리케이션 데이터를 표시하고 사용자와 상호작용하는 것이다.

UI Layer는 Data Layer에서 가져온 애플리케이션 상태를 시각적으로 나타낸다.

 

 

 

MVVM 예제 코드

 

의존성 추가

dependencies{
    implementation("androidx.activity:activity-ktx:1.9.1")
    implementation("androidx.fragment:fragment-ktx:1.8.2")
}

viewModels()를 사용하기 위해 의존성을 추가해야한다.

둘 중 아무거나 추가하면 된다.

 

 

MvvmUiState

// 게시판 ui
data class MvvmUiState (
    val header: String?,
    val title: String?,
    val content: String?,
    val user: String?,
    val viewCount: Int
){
    companion object{
        fun empty(
            header: String? = null,
            title: String? = null,
            content: String? = null,
            user: String? = null,
            viewCount: Int = 0
        ) = MvvmUiState(
            header = header,
            title = title,
            content = content,
            user = user,
            viewCount = viewCount
        )
    }
}

UI의 상태를 표현하기 위해 사용되는 데이터 클래스이다.

 

empty 함수는 해당 데이터클래스의 인스터스를 기본값으로 생성할 수 있게 해준다.

empty companion object 클래스에 정의되어 있어 정적으로 호출할  있다.

 

 

 

MvvmViewModel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class MvvmViewModel : ViewModel() {
    // ui의 상태를 담고있는 변수로 MvvmUiState.empty()로 초기값을 설정한다.
    private val _uiState = MutableStateFlow(MvvmUiState.empty())
    
    // _uiState를 StateFlow 타입으로 정의 후 외부에 불변 상태로 노출시킨다.
    val uiState: StateFlow<MvvmUiState> = _uiState.asStateFlow()
	
    // 데이터를 요청하는 함수
    fun requestBoard() {
    	// api 호출 or 데이터 가져오는 로직이 들어가야함
    	
        // ui 상태 업데이트
        viewModelScope.launch {
            _uiState.update { prev ->
                prev.copy(
                    header = "내일배움캠프 게시판",
                    title = "Compose 강의",
                    content = "MVVM 디자인 패턴과 compose",
                    user = "장세진",
                    viewCount = 1000
                )
            }
        }
    }
}

뷰 모델에서는 ui의 상태를 선언하고, 데이터 요청 함수를 작성한다.

외부에서 ui의 상태를 읽을 수는 있지만, 변경할 수는 없다.

 

viewModelScope.launch { ... } : 블록 내에서 코루틴을 사용하여 비동기 작업을 실행함
_uiState.update { ... } : 현재 상태를 기반으로 새로운 상태를 생성함
prev.copy(...) : 기존 상태의 복사본을 만들고, 필요한 속성만 변경함

해당 함수들을 사용하여 ui의 상태를 업데이트한다.

 

 

MvvmActivty

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

class MvvmActivity: ComponentActivity() {

    private val viewModel: MvvmViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initViewModel()
        viewModel.requestBoard()
    }

    private fun initViewModel(){
    	// 생명주기 범위 내에서 코루틴 실행 
        lifecycleScope.launch {
            // uiState 흐름을 관찰하고, 최신 상태를 수집
            viewModel.uiState.flowWithLifecycle(lifecycle).collectLatest {
                // UI 상태의 변화를 로그로 확인
                state -> Log.d("jess", state.toString())
            }
        }
    }
}

MVVM 패턴에서 액티비티는 ComponentActivity 클래스를 상속받아 구현된다.

 

viewModel은 MvvmViewModel 인스턴스를 사용하며

by viewModels() 델리게이트를 사용하여 ViewModel을 초기화한다.

 

onCreate에서 뷰모델을 초기화한 뒤 뷰모델에 데이터를 요청한다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함