1. Jetpack Compose란?
Jetpack Compose는 Android의 최신 UI 툴킷으로, 선언형(Declarative) 방식을 기반으로 UI를 구성할 수 있도록 설계되었다. 기존의 XML 기반 UI 작성 방식보다 직관적이며, 코드 양을 줄이고, 재사용성을 높일 수 있는 장점이 있다.
Compose는 Kotlin 언어를 기반으로 동작하며, 보다 유연한 UI 개발이 가능하다. 특히 상태(State) 기반의 UI 렌더링 방식을 지원하여 동적인 UI를 효율적으로 관리할 수 있다.
2. Jetpack Compose의 주요 특징
선언형 UI (Declarative UI)
기존 XML 방식은 명령형(Imperative) 방식으로, UI 요소를 직접 조작하고 업데이트해야 했다. 하지만 Compose는 선언형 방식을 채택하여 상태(State)에 따라 UI가 자동으로 갱신된다. 예를 들어, findViewById()
를 사용하지 않고도 UI를 쉽게 업데이트할 수 있다.
@Composable
fun CounterApp() {
var count by remember { mutableStateOf(0) }
Column {
Text(text = "Count: $count", fontSize = 20.sp)
Button(onClick = { count++ }) {
Text("Increase")
}
}
}
위 코드에서 count
값이 변경될 때마다 UI가 자동으로 다시 렌더링된다.
더 적은 코드 (Less Boilerplate)
- XML과
findViewById()
,ViewBinding
없이 UI를 직접 Kotlin 코드로 작성할 수 있다. RecyclerView
및Adapter
없이 리스트 UI를 간단하게 구현할 수 있다.
재사용성 및 확장성
- UI 컴포넌트를 Composable 함수로 만들어 쉽게 재사용할 수 있다.
- XML 기반에서는
<include>
태그를 활용해 재사용했지만, Compose에서는 Composable 함수를 이용하면 더욱 직관적이고 효율적이다.
@Composable
fun CustomButton(text: String, onClick: () -> Unit) {
Button(onClick = onClick) {
Text(text)
}
}
이제 CustomButton("Click Me") { /* 이벤트 핸들링 */ }
와 같이 쉽게 사용할 수 있다.
애니메이션 및 UI 업데이트가 쉬움
Modifier
와animate*()
API를 활용해 자연스러운 애니메이션을 쉽게 추가할 수 있다.
@Composable
fun AnimatedBox() {
var isVisible by remember { mutableStateOf(true) }
val alpha by animateFloatAsState(targetValue = if (isVisible) 1f else 0f)
Column {
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red)
.alpha(alpha)
)
Button(onClick = { isVisible = !isVisible }) {
Text("Toggle Visibility")
}
}
}
Kotlin과의 강력한 연계
Compose는 Kotlin 언어와 100% 호환되며, 코루틴(Coroutines) 및 Flow와 같은 최신 Kotlin 기능과도 쉽게 결합할 수 있다. 따라서 비동기 작업 처리가 훨씬 간편해진다.
@Composable
fun LoadDataScreen() {
val scope = rememberCoroutineScope()
var text by remember { mutableStateOf("Loading...") }
LaunchedEffect(Unit) {
scope.launch {
delay(2000)
text = "Data Loaded"
}
}
Text(text)
}
3. XML과 Jetpack Compose 비교
항목 | XML 기반 (View System) | Jetpack Compose |
---|---|---|
UI 구성 방식 | 명령형 (Imperative) | 선언형 (Declarative) |
코드 스타일 | XML + Kotlin/Java 분리 | Kotlin 코드 내에서 UI 작성 |
View 참조 | findViewById() , View Binding 필요 |
Composable 함수로 직접 사용 |
상태 관리 | LiveData , ViewModel , Data Binding 사용 |
remember , mutableStateOf() 활용 |
UI 변경 방식 | setText() , setVisibility() 등 수동 업데이트 |
상태 변경 시 자동 UI 업데이트 |
RecyclerView | Adapter + ViewHolder 필요 | LazyColumn , LazyRow 로 간편 구현 |
애니메이션 | ObjectAnimator , ViewPropertyAnimator 필요 |
animate*() API 사용 |
다크 모드 대응 | night 테마 XML 필요 |
isSystemInDarkTheme() 활용 |
4. XML vs Compose UI 코드 비교
기본 UI 생성 (TextView 예제)
XML 방식
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="20sp"/>
val textView: TextView = findViewById(R.id.textView)
textView.text = "Updated Text"
Jetpack Compose 방식
@Composable
fun Greeting() {
Text(text = "Hello World!", fontSize = 20.sp)
}
RecyclerView vs LazyColumn
XML + RecyclerView 방식
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
class MyAdapter(private val items: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = items[position]
}
override fun getItemCount() = items.size
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.textView)
}
}
recyclerView.adapter = MyAdapter(listOf("Item 1", "Item 2", "Item 3"))
Jetpack Compose 방식 (LazyColumn)
@Composable
fun ItemList(items: List<String>) {
LazyColumn {
items(items) { item ->
Text(text = item, fontSize = 20.sp, modifier = Modifier.padding(8.dp))
}
}
}
5. ComposeUI와 XML의 UI 렌더링 방식 비교
https://superohinsung.tistory.com/380
[Android] Jetpack Compose의 Recomposition 정리
1. Recomposition(리컴포지션)이란?Recomposition(리컴포지션)은 Jetpack Compose에서 상태(State)의 변경에 따라 필요한 UI만 다시 그리는 과정을 의미한다.기존 XML 기반 View 시스템에서는 findViewById()를 통해 특
superohinsung.tistory.com
XML 기반 View 시스템
- XML을 기반으로 View를 정의하고,
findViewById()
또는 ViewBinding을 통해 객체화한 후 UI를 조작한다. - 뷰 계층 구조가 트리(Tree) 형태로 구성되며, UI 변경 시 특정 View를 찾아 업데이트해야 한다.
- View는 명령형 방식(Imperative)으로 상태를 직접 변경해야 한다.
- UI 업데이트 시 invalidate() 또는 requestLayout() 호출이 필요할 수 있다.
Jetpack Compose UI 렌더링 방식
Composable
함수가 상태(State)에 따라 UI를 렌더링한다.- 변경된 부분만 자동으로 다시 그려지는 Recomposition 개념이 적용된다.
- UI 변경 시 전체 View를 다시 그리는 것이 아니라, 상태가 변경된 부분만 렌더링되므로 성능이 최적화된다.
- UI와 로직이 하나의 함수 내에서 관리될 수 있어 분리와 재사용성이 뛰어남
@Composable
fun Greeting(name: String) {
Text("Hello, $name")
}
이 함수가 호출될 때마다 새로운 Text()
가 그려지는 것이 아니라, name
값이 변경될 때만 해당 UI가 다시 렌더링된다.
6. 마무리
Jetpack Compose는 기존 XML 기반 UI 시스템보다 간결하고 유지보수가 쉬우며, 최신 Android 개발 트렌드에 맞는 강력한 UI 툴킷이다. 특히 상태 기반 UI 업데이트, 선언형 방식의 코드 구조, Kotlin과의 강력한 연계성으로 인해 새로운 Android 프로젝트에서 적극 고려할 가치가 있다.
'Android > Study' 카테고리의 다른 글
[Android] 인텐트(Intent) 및 인텐트 필터(Intent Filter) (0) | 2025.02.20 |
---|---|
[Android] Jetpack Compose의 Recomposition 정리 (0) | 2025.02.20 |
[Android] SearchView 사용기 (0) | 2024.06.24 |
[Android] WebView 사용기 (0) | 2024.06.24 |
[Android] WebSocket를 통해서 채팅 기능 구현 feat. Clean Architecture, Hilt (0) | 2024.06.24 |