Jetpack Compose는 Android의 최신 UI 툴킷으로, 선언형(Declarative) 방식으로 UI를 구성할 수 있도록 지원합니다. 기존의 XML 기반 UI 갭라 방식과 달리, Kotlin 코드만으로 화면을 구성할 수 있어 개발 생산성이 크게 향상됩니다.
Jetpack Compose는 선언형(Declarative) 방식의 UI 프레임워크로, 개발자가 UI의 상태를 직접 정의하면 Compose가 이를 자동으로 업데이트해 줍니다. 기존의 XML 기반 UI 개발 방식에서는 UI 요소를 변경할 때 findViewById를 이용하거나 ViewModel과 LiveData를 활용해야 했지만, Compose에서는 단순히 상태(state) 변화를 감지하여 UI를 갱신할 수 있습니다.
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}
위 코드처럼 @Composable annotation을 사용하여 UI를 구성할 수 있습니다.
Jetpack Compose에서는 XML과 Kotlin 코드를 분리할 필요 없이, 모든 UI 로직을 Kotlin 코드로 작성할 수 있습니다. UI 컴포넌트는 함수로 정의되며, 함수형 프로그래밍 스타일을 적용할 수 있어 재사용성이 높아집니다.
@Composable
fun UserProfile(name: String, age: Int) {
Column {
Text(text = "이름: $name")
Text(text = "나이: $age")
}
}
Jetpack Compose는 기존 View 시스템과도 호환되므로, 기존 프로젝트에서도 점진적으로 Compose를 도입할 수 있습니다. ComposeView를 사용하면 기존 XML 기반 UI와 Compose UI를 함께 사용할 수도 있습니다.
val composeView = ComposeView(context).apply {
setContent {
Text("Hello from Compose")
}
}
Compose는 MaterialTheme을 제공하여 쉽게 디자인 시스템을 적용할 수 있습니다.
@Composable
fun ThemedText() {
MaterialTheme {
Text("Jetpack Compose 테마 적용!", style = MaterialTheme.typography.h6)
}
}
Jetpack Compose에서는 간단한 코드로 애니메이션을 적용할 수 있습니다.
@Composable
fun AnimatedBox() {
var isExpanded by remember { mutableStateOf(false) }
val size by animateDpAsState(if (isExpanded) 200.dp else 100.dp)
Box(
Modifier
.size(size)
.background(Color.Blue)
.clickable { isExpanded = !isExpanded }
)
}
Jetpack Compose는 다양한 상태 관리 기법을 제공하여 UI를 효율적으로 업데이트할 수 있습니다. 대표적으로 remember와 mutableStateOf를 활용하는 방식이 있습니다. Compose에서는 remember와 mutableStateOf를 사용하여 UI가 재구성될 때 상태를 유지할 수 있습니다. remember는 Composable 함수 내에서 상태를 저장하고 유지하는 역할을 하며, mutableStateOf는 상태 변화를 추적하여 UI를 자동으로 갱신합니다.
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Column {
Text(text = "Count: $count")
Button(onClick = { count++ }) {
Text("증가")
}
}
}
위 예제에서 count 상태는 remember를 통해 저장되며, 버튼을 클릭할 때마다 값이 증가합니다. 이때 mutableStateOf를 사용하여 Compose가 count 값의 변경을 감지하고 UI를 자동으로 다시 렌더링합니다.
예를 들어, 아래 코드는 remember 없이 상태를 관리하는 경우와 비교했을 때 큰 차이를 보입니다.
@Composable
fun CounterWithoutRemember() {
var count = mutableStateOf(0) // UI 갱신이 되지 않음
Column {
Text(text = "Count: ${count.value}")
Button(onClick = { count.value++ }) {
Text("증가")
}
}
}
위 코드에서는 remember를 사용하지 않기 때문에 count가 UI가 다시 그려질 때마다 초기화됩니다. 따라서 버튼을 클릭해도 카운트가 증가하지 않습니다. remember는 화면 회전과 같은 구성 변경(Configuration Change)이 발생하면 상태를 유지하지 못합니다. 이를 해결하기 위해 rememberSaveable을 사용할 수 있습니다.
@Composable
fun CounterWithSaveable() {
var count by rememberSaveable { mutableStateOf(0) }
Column {
Text(text = "Count: $count")
Button(onClick = { count++ }) {
Text("증가")
}
}
}
rememberSaveable을 사용하면 화면 회전이 발생해도 count 상태가 유지됩니다.