# Jetpack Compose의 특징
## 반응형 프로그래밍 모델
Jetpack Compose는 **UI 개발을 간소화**하기 위해 설계된 최신 툴킷이다.
**반응형 프로그래밍 모델**을 Kotlin 프로그래밍 언어의 간결함 및 사용 편의성과 결합한다.
즉, 선언적인 접근 방식으로 데이터를 UI 계층 구조로 변환하는 **일련의 함수를 호출**하여 UI를 구성한다.
기본 데이터가 변경되면 프레임워크가 이러한 함수를 자동으로 다시 실행하여 UI 계층 구조를 업데이트한다.
## 구성 가능한 함수
Compose앱은 구성 가능한 함수(컴포저블)로 구성된다.
구성 가능한 함수는 `@Composable` 이라는 어노테이션이 붙어있는 함수이며, 다른 구성 가능한 함수를 호출 가능하다.
새로운 UI 구성요소를 만들기 위해서는 함수만 있으면 된다.
재사용이 가능한 작은 컴포저블을 만들면 앱에 사용하는 UI 요소의 라이브러리를 쉽게 빌드할 수 있으며, 각 요소는 화면의 한 부분을 담당하며 독립적으로 수정할 수 있다.
```
/* 예시 코드 - Greeting 이라는 구성 가능한 함수가
라이브러리에서 제공하는 구성 가능한 함수인 Text를 호출한다.
이 함수는 지정된 입력(String)을 표시하는 UI 계층 구조를 생성한다.
*/
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
```
# UI 조정
## 배경 색상 설정
다음의 코드는 기본 흰색 배경에 검정색 글자로 된 UI를 생성한다.
```
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
```
다른 배경 색상을 설정하기 위해 `Text` 컴포저블을 색상이 설정된 `Surface`로 래핑할 수 있다.
```
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(color = MaterialTheme.colorScheme.primary) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
}
```
이때, 텍스트 색상은 따로 지정하지 않았지만, 배경에 맞는 흰색으로 적용된다. 이는 `androidx.compose.material3.Surface`와 같은 Material 구성요소에 자동으로 적용되는 편의 기능이다. 반면에 유연성은 떨어진다는 단점이 있다.
위 예에서, `Surface`는 배경이 primary 색상으로 설정될 때 배경 위의 모든 텍스트가 테마에도 정의된 onPrimary 색상을 사용해야 한다는 것을 인식한다.
## 수정자 (Modifier)
위에서 사용한 `Surface` 및 `Text`와 같은 대부분의 Compose UI 요소는 `modifier` 매개변수를 선택적으로 허용한다.
수정자는 상위 요소 레이아웃 내에서 UI 요소가 배치되고 표시되고 동작하는 방식을 UI 요소에 알려준다.
아래 코드에서는 `Text` 컴포지션에 패딩 수정자를 전달한다.
이때 체이닝을 통해 여러 수정자를 추가할 수도 있다.
```
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(color = MaterialTheme.colorScheme.primary) {
Text(
text = "Hello $name!",
modifier = modifier.padding(24.dp)
)
}
}
```
아래 링크에서 Compose의 수정자 목록을 확인할 수 있다.
https://developer.android.com/develop/ui/compose/modifiers-list?hl=ko
## 열과 행 만들기
Column 컴포저블을 이용하여 세로로 요소를 배치할 수 있습니다.
```
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(color = MaterialTheme.colorScheme.primary) {
Column(modifier = modifier.padding(24.dp)) {
Text(text = "Hello ")
Text(text = name)
}
}
}
```
Row 컴포저블을 이용하여 요소를 가로로 배치할 수 있습니다.
```
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(vertical = 4.dp, horizontal = 8.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier.weight(1f)) {
Text(text = "Hello ")
Text(text = name)
}
ElevatedButton(
onClick = { /* TODO */ }
) {
Text("Show more")
}
}
}
}
```
## Compose에서의 상태
위에서 언급한 반응형 프로그래밍의 일종으로, 변환된 데이터가 UI에 자동으로 반영되게 하려면 Compose에서 해당 데이터를 추적할 수 있도록 등록해야합니다. 추적되는 데이터를 '상태'라고 합니다.
컴포저블에 내부 상태를 추가하려면 mutableStateOf 함수를 사용하면 됩니다.
이때, remember를 사용하지 않고, 그냥 mutableStateOf 함수만을 변수에 할당하게 되면, 화면이 새로 갱신 (리컴포지션) 될 때마다 값이 초기값으로 초기화되기 때문에 이전 상태를 기억하려면 remember 함수를 써야합니다.
```
@Composable
fun Greeting(...) {
val expanded = remember { mutableStateOf(false) }
// ...
}
```