— Compose를 Compose답게 사용하는 방법

Compose를 처음 배우면 보통 가장 먼저 보게 되는 것은 이런 코드입니다.

@Composable
fun Greeting() {
    Text("Hello")
}

그리고 처음에는:

“생각보다 간단하네?”

라고 느끼기 쉽습니다.

하지만 실제로 Compose에서 중요한 것은:

  • Text()
  • Button()
  • Column()

같은 UI 문법이 아닙니다.

진짜 중요한 것은:

상태(State)
+
Recomposition
+
Data Flow

입니다.

Compose는 단순 UI Toolkit이 아니라:

“상태 기반 UI 시스템”

이기 때문입니다.

이번 글에서는 Compose에서 반드시 이해해야 하는 핵심 개념들을 정리해보겠습니다.


1. @Composable — Compose UI의 기본 단위

Compose의 모든 UI는 Composable 함수로 구성됩니다.

예:

@Composable
fun Greeting(name: String) {

    Text("Hello $name")
}

그리고 Composable은 다른 Composable을 조합합니다.

@Composable
fun HomeScreen() {

    Column {

        Greeting("Android")

        Button(onClick = {}) {
            Text("확인")
        }
    }
}

즉 Compose는:

함수 조합 기반 UI

입니다.


기존 View 시스템과 차이

기존 Android는:

View 객체 생성
→ 속성 변경
→ View Tree 구성

방식이었습니다.

Compose는:

Composable 함수 실행
→ 현재 UI 계산

방식입니다.

즉:

객체 중심 UI
→ 함수 중심 UI

라는 변화가 발생합니다.


2. State — Compose의 핵심

Compose에서 가장 중요한 개념은 State입니다.

Compose를 한 문장으로 설명하면:

UI = f(state)

입니다.

즉:

“현재 상태가 무엇인가?”

만 정의하면 UI가 자동으로 구성됩니다.


가장 기본적인 State

var count by remember {
    mutableStateOf(0)
}

여기서 중요한 것은:

  • mutableStateOf
  • remember

입니다.


State 변경

Button(
    onClick = { count++ }
) {
    Text("$count")
}

count가 바뀌면 Compose는 UI를 다시 계산합니다.


핵심 사고

Compose에서는:

UI를 직접 수정하지 않는다.

대신:

상태를 변경한다.

그리고 UI는 상태를 기반으로 다시 계산됩니다.


3. Recomposition — Compose의 핵심 메커니즘

Compose에서 반드시 이해해야 하는 개념입니다.


Recomposition이란?

State가 바뀌면 필요한 UI만 다시 계산하는 메커니즘입니다.

예:

Text("$count")

count가 변경되면 이 부분만 다시 계산됩니다.


기존 Android 사고

기존에는:

invalidate()
notifyDataSetChanged()
requestLayout()

처럼:

UI 갱신을 직접 지시

했습니다.


Compose 사고

Compose에서는:

상태 변경
→ Compose가 필요한 부분 재계산

합니다.

즉:

“무엇을 다시 그릴까?”

를 개발자가 직접 관리하지 않습니다.


Recomposition에서 중요한 것

실무에서는 여기서 차이가 많이 납니다.

중요한 개념:

  • Stable
  • Immutable
  • recomposition scope
  • unnecessary recomposition

특히:

불필요한 recomposition 최소화

가 성능의 핵심입니다.


4. remember — 상태 유지

Compose 함수는 상태가 바뀔 때마다 다시 실행됩니다.

따라서 단순 변수는 유지되지 않습니다.

예:

var count = 0

이렇게 하면 recomposition 시 초기화됩니다.


remember 사용

var count by remember {
    mutableStateOf(0)
}

remember는:

recomposition 사이에서 값을 유지

합니다.


remember를 이해하는 것이 중요한 이유

Compose 초보자가 가장 많이 헷갈리는 부분 중 하나입니다.

Compose 함수는:

"한 번 실행되는 UI 코드"

가 아니라

"상태 변화마다 다시 호출되는 함수"

입니다.


5. rememberSaveable — 화면 회전 대응

Android 개발자에게 매우 중요한 개념입니다.


기존 Android

우리는 오랫동안:

onSaveInstanceState()

를 다뤘습니다.


Compose

Compose에서는:

var text by rememberSaveable {
    mutableStateOf("")
}

를 사용합니다.

rememberSaveable은:

  • 화면 회전
  • process recreation

시 상태를 복원합니다.


사고 변화

기존 Android:

Lifecycle 이벤트 대응

Compose:

상태 보존 전략

6. Modifier — Compose의 Layout/Style 시스템

Compose에서 매우 중요한 개념입니다.

예:

Text(
    "Hello",
    modifier = Modifier
        .padding(16.dp)
        .fillMaxWidth()
)

Modifier는:

  • layout
  • padding
  • click
  • background
  • animation

등을 연결합니다.


Modifier에서 중요한 점

순서가 중요

예:

Modifier
    .background(Color.Red)
    .padding(16.dp)

Modifier
    .padding(16.dp)
    .background(Color.Red)

는 결과가 다릅니다.


Compose의 특징

Modifier는:

체인 기반 UI 구성

입니다.

일종의 함수 조합에 가깝습니다.


7. Layout — Compose의 기본 구조

Compose는 XML Layout 대신 Layout Composable을 사용합니다.

기본 3개:

  • Column
  • Row
  • Box

Column

세로 배치.

Column {

    Text("A")

    Text("B")
}

Row

가로 배치.

Row {

    Text("A")

    Text("B")
}

Box

겹치기.

Box {

    Image(...)

    Text("Overlay")
}

실무에서 중요한 Layout

특히 많이 사용하는 것:

  • LazyColumn
  • LazyRow
  • ConstraintLayout
  • FlowRow

8. State Hoisting — 상태는 위로 올린다

Compose Architecture에서 매우 중요합니다.


좋지 않은 구조

TextField 내부에서 상태 관리

좋은 구조

ViewModel에서 상태 관리

예:

TextField(
    value = text,
    onValueChange = onTextChanged
)

즉:

UI는 상태를 보여주기만 한다.


왜 중요한가?

State Hoisting을 하면:

  • 테스트 용이
  • 재사용성 증가
  • UDF 구조 가능
  • ViewModel 연결 쉬움

장점이 생깁니다.


9. Unidirectional Data Flow (UDF)

Compose와 매우 잘 맞는 구조입니다.

핵심:

State ↓
Event ↑

구조

ViewModel
   ↓
UI State
   ↓
Compose UI
   ↑
User Event

Compose는 이 구조와 매우 잘 맞습니다.


10. Side Effect — Compose에서 가장 헷갈리는 부분

Compose 함수는 가능한 순수 함수처럼 동작해야 합니다.

하지만 실제 앱은:

  • API 호출
  • Navigation
  • Toast
  • Animation
  • Coroutine

등이 필요합니다.

이를 위한 것이 Side Effect API입니다.


중요한 SideEffect들

LaunchedEffect

LaunchedEffect(Unit) {

    viewModel.loadData()
}

DisposableEffect

리소스 정리.


rememberCoroutineScope

Compose 내부 coroutine 실행.


초보자가 자주 하는 실수

Composable 내부에서
API를 직접 반복 호출

→ 무한 호출 발생.


11. Compose에서 가장 중요한 Architecture

실무에서는 결국 이 구조가 핵심입니다.

Repository
   ↓
ViewModel
   ↓
StateFlow
   ↓
Compose UI

Compose는:

Reactive State Architecture

와 가장 잘 맞습니다.


12. Compose를 잘한다는 것의 의미

많은 사람들이:

Animation
Custom UI
Fancy UI

를 Compose 실력이라고 생각합니다.

하지만 실제 중요한 것은:

State 설계
+
Data Flow 설계
+
Recomposition 이해

입니다.


Android 개발자가 가장 어려워하는 부분

보통 여기서 많이 막힙니다.


1. Recomposition 이해 부족

→ 성능 문제 발생.


2. State 위치 설계 실패

→ 상태 꼬임 발생.


3. SideEffect misuse

→ 무한 호출 발생.


4. mutable object 남용

→ recomposition 추적 어려움.


마무리

Compose는 단순히:

새로운 UI 문법

이 아닙니다.

실제로는:

상태(State) 기반 UI Architecture

입니다.

그리고 Compose를 제대로 이해하려면:

  • Composable
  • State
  • Recomposition
  • remember
  • Modifier
  • State Hoisting
  • UDF
  • SideEffect

를 하나의 흐름으로 이해해야 합니다.

결국 Compose의 핵심은:

UI를 직접 조작하는 것

이 아니라

상태 흐름을 설계하는 것

입니다.

다음 글에서는:

“Compose를 어떻게 학습하면 좋은가?”

를 실제 예제 중심으로 정리해보겠습니다.

+ Recent posts