
Android 애플리케이션을 개발할 때 UI를 구현하는 방식은 크게 “안드로이드 View 시스템(XML 사용)”과 “Jetpack Compose(코틀린 기반)”로 나뉩니다.
이 글에서는 Jetpack Compose란 무엇인지, 기존 View 시스템과의 차이점, Compose를 사용해야 하는 이유 등을 설명하겠습니다.
Jetpack Compose는 Google이 제공하는 최신 UI 툴킷으로, 기존 XML 방식이 아닌 Kotlin 코드만으로 UI를 선언형(Declarative)으로 작성할 수 있는 기술입니다.
기존 안드로이드 UI는 일반적으로 XML과 Activity/Fragment를 사용하여 구성합니다. 하지만 Jetpack Compose는 XML 없이 Kotlin 코드만으로 UI를 선언적으로 작성할 수 있습니다.
또한, Jetpack Compose는 Activity 없이도 UI를 테스트하거나 쉽게 재사용할 수 있다는 장점이 있습니다.
🔴 기존 View 시스템 방식
<!-- XML 파일 (activity_main.xml) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="안녕하세요, Compose!"
android:textSize="20sp"
android:textColor="@color/black"/>
// Kotlin 코드 (Activity에서 XML을 연결)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
🟢 Jetpack Compose 방식
@Composable
fun Greeting() {
Text(text = "안녕하세요, Compose!", fontSize = 20.sp, color = Color.Black)
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting() // 직접 UI를 렌더링
}
}
}
🚀 차이점 정리
| 기존 View 시스템 | Jetpack Compose |
|---|---|
| XML 또는 코드(Java, Kotlin)로 UI 정의 | Kotlin 코드만으로 UI 선언 |
findViewById(), 바인딩 방식 사용 | UI 요소를 직접 호출 가능 |
| 명령형(Imperative) 방식 | 선언형(Declarative) 방식 |
| ViewModel을 통해 상태 관리 (MVVM 패턴을 활용 시) | ViewModel 뿐만 아니라 remember, rememberSaveable 등으로 UI 상태 관리 가능 |
| 레이아웃을 변경하려면 XML 수정 필요 | 함수형 컴포저블 조합으로 UI 재사용 용이 |
| XML 및 코드 분리가 필요하여 관리 어려움 | UI와 로직이 같은 Kotlin 파일에 있어 가독성 향상 |
Jetpack Compose를 사용하면 기존 UI 개발 방식보다 코드량이 줄어들고, UI의 가독성이 높아지며, 개발 속도가 향상됩니다.
기존 View 시스템에서는 XML + Kotlin 코드가 필요했지만, Compose는 Kotlin 코드 하나로 UI를 구성할 수 있습니다. 실제로, Jetpack Compose를 활용하여 UI 코드 라인 수가 60% 이상 줄었다는 내용을 Android Developers Blog 들을 통해 확인할 수 있습니다.
✅ 기존 View 방식 (XML + Kotlin)
<!-- xml 코드 -->
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="클릭 횟수: 0"/>
// Activity 코드
val button = findViewById<Button>(R.id.button)
var count = 0
button.setOnClickListener {
count++
button.text = "클릭 횟수: $count"
}
✅ Jetpack Compose 방식
var count by remember { mutableStateOf(0) } // 상태를 기억하고 변화 감지하여 UI 갱신
// remember 와 mutableStateOf 에 대해서는 추후 다룰 예정입니다.
// 여기서는 코드가 어떻게 작성되는지만 보고 넘어가셔도 좋습니다.
Button(onClick = { count++ }) {
Text(text = "클릭 횟수: $count")
}
➡️ 버튼을 누를 때마다 UI가 자동으로 갱신됩니다. 별도의 setText() 호출이 필요하지 않습니다.
Compose는 UI를 코드로 선언하는 방식이기 때문에 구조가 단순하고, 가독성이 뛰어나며, 유지보수가 쉬운 코드 작성이 가능합니다.
또한 상태(State)의 변경이 UI에 자동으로 반영되기 때문에, UI 업데이트 로직을 별도로 작성할 필요가 없습니다.
✅ 기존 View 방식 (명령형 UI)
val button = findViewById<Button>(R.id.button)
val textView = findViewById<TextView>(R.id.textView)
button.setOnClickListener {
textView.text = "버튼이 클릭됨"
}
✅ Jetpack Compose 방식 (선언형 UI)
var text by remember { mutableStateOf("클릭 전") }
Button(onClick = { text = "버튼이 클릭됨" }) {
Text(text = text)
}
text)만 선언하고 변경하면 UI가 자동으로 업데이트되므로, 로직이 단순하고 직관적입니다.➡️ UI의 상태를 직접 업데이트하는 복잡한 로직 대신, 데이터(state)를 선언하고 변화만 주면 되기 때문에 전체 UI 흐름이 명확하게 드러나며 가독성이 뛰어납니다.
안드로이드 View 시스템을 많이 다뤄보지 않은 사람이라면, 예제만으로는 이 장점이 쉽게 와닿지 않을 수 있습니다. 예를 들어 기존 View 시스템에서는 리스트에 아이템을 추가하려면 Adapter를 갱신하고,
notifyDataSetChanged()를 호출하는 등 여러 절차가 필요합니다.반면 Compose에서는 리스트의 상태만 변경하면 UI가 자동으로 갱신되므로, 전체 흐름이 단순해지고 가독성도 훨씬 향상됩니다.
관련된 내용 역시 나중에 다룰 예정이니 지금은 이해가 다 되지 않아도 괜찮습니다.
Compose는 Android Studio의 Preview 기능을 지원하여 UI를 실시간으로 확인할 수 있습니다.
✅ 기존 XML의 Preview 방식
✅ Jetpack Compose Preview
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun PreviewGreeting() {
Greeting()
}
➡️ 다크 모드, 다양한 화면 크기 적용 등 즉시 확인 가능합니다.
➡️ 동적인 UI(버튼 클릭, 리스트 스크롤 등)도 Interactive Mode를 통해 미리 볼 수 있습니다.
📌 XML도 Preview가 가능하지만, Compose Preview는 테마 변경 및 동적 UI 테스트가 더 용이합니다.
Jetpack Compose는 기존 XML 기반 UI와 함께 사용할 수 있으므로, 기존 프로젝트에 점진적으로 도입하는 것이 가능합니다.
✅ ComposeView를 활용하여 XML 내부에서 Compose UI를 사용할 수 있습니다.
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
findViewById<ComposeView>(R.id.compose_view).setContent {
Greeting()
}
✅ 기존 View를 Compose 내부에서도 사용할 수 있습니다.
AndroidView(
factory = { context ->
TextView(context).apply {
text = "기존 View 시스템"
}
}
)
➡️ 즉, Compose는 기존 UI와 함께 사용할 수 있어 점진적인 리팩토링을 할 수 있습니다.
Jetpack Compose는 선언형 UI와 상태 기반 관리를 중심으로 발전하고 있는 현대적인 UI 개발 패턴과 자연스럽게 결합할 수 있습니다.
✅ Material 3 지원
MaterialTheme을 활용하여 쉽게 테마 설정 가능합니다.MaterialTheme(
colorScheme = darkColorScheme()
) {
Text("다크 모드 적용됨")
}
✅ MVVM, MVI 패턴과 결합 가능
ViewModel을 사용하여 UI와 데이터를 분리했는데, Compose에서도 ViewModel을 그대로 활용할 수 있습니다.@Composable
fun Greeting(viewModel: MainViewModel = viewModel()) {
val name by viewModel.name.collectAsState()
Text(text = "안녕하세요, $name!")
}
✅ Flow, LiveData 등 최신 상태 관리 방식과 연동 가능
LiveData를observe()로 감지해야 했지만, Compose에서는 collectAsState()를 사용하여 Flow 데이터를 바로 UI에 반영할 수 있습니다.@Composable
fun UserList(viewModel: UserViewModel = viewModel()) {
val users by viewModel.users.collectAsState(initial = emptyList())
LazyColumn {
items(users) { user ->
Text(text = user.name)
}
}
}
➡️ Compose는 최신 상태 관리 패턴과의 연동이 자연스럽고 코드가 간결합니다.
✅ Jetpack Compose는 기존 View 시스템보다 더 쉽고 직관적인 방식으로 UI를 만들 수 있는 최신 UI 프레임워크입니다.
특히 코드량 감소, 가독성 향상, 빠른 UI 미리보기, 선언형 UI 방식 등 강력한 장점을 제공합니다.
📢 2023년부터 Google이 Jetpack Compose를 공식 UI 프레임워크로 권장하고 있으므로, 학습하는 것이 필수적입니다.
이제 Jetpack Compose의 개념을 이해했으니, 다음 글에서는 Compose 개발을 위한 환경을 어떻게 설정하는지 설명하겠습니다.
Android Studio에서 Compose 프로젝트를 만들고 첫 번째 Compose UI를 실행하는 방법까지 배워보겠습니다. 🚀