— View 중심 사고에서 State 중심 사고로

Compose를 처음 보면 많은 Android 개발자들이 이렇게 느낍니다.

“XML 대신 Kotlin으로 UI 만드는 거네?”

 

하지만 실제로 Compose의 가장 큰 변화는 문법이 아닙니다.

진짜 변화는:

객체(View) 중심 사고
→
상태(State) 중심 사고

로의 이동입니다.

 

이 변화는 생각보다 훨씬 큽니다.

왜냐하면 Android 개발자들은 오랫동안:

  • View 객체를 만들고
  • 직접 수정하고
  • 이벤트를 연결하고
  • Lifecycle을 따라 상태를 관리하는 방식

에 익숙해져 있었기 때문입니다.

Compose는 이 흐름 자체를 바꾸려고 합니다.


기존 Android 개발 방식

전통적인 Android UI는 기본적으로:

“화면 객체(View)를 직접 조작”

 

하는 방식이었습니다.

예를 들어 로그인 버튼 활성화.


기존 View 방식

button.isEnabled =
    idEditText.text.isNotBlank() &&
    passwordEditText.text.isNotBlank()

우리는 자연스럽게:

Button 객체를 직접 수정

합니다.

즉 사고 흐름이:

현재 UI 객체 상태를 어떻게 변경할까?

입니다.


Compose의 사고 방식

Compose에서는 완전히 다르게 접근합니다.

@Composable
fun LoginScreen() {

    var id by remember { mutableStateOf("") }
    var pw by remember { mutableStateOf("") }

    val enabled = id.isNotBlank() &&
                  pw.isNotBlank()

    Column {

        TextField(
            value = id,
            onValueChange = { id = it }
        )

        TextField(
            value = pw,
            onValueChange = { pw = it }
        )

        Button(
            enabled = enabled,
            onClick = {}
        ) {
            Text("로그인")
        }
    }
}

여기서는:

button.enable()

같은 코드가 없습니다.

Compose에서는:

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

만 정의합니다.


가장 중요한 사고 변화

Compose를 배우며 가장 중요한 변화는 이것입니다.


기존 Android 사고

UI를 어떻게 조작할까?

Compose 사고

현재 상태를 어떻게 표현할까?

이 차이는 단순 문법 차이가 아닙니다.

Architecture 전체에 영향을 줍니다.


RecyclerView 사고 vs LazyColumn 사고

Android 개발자들이 가장 크게 체감하는 변화 중 하나입니다.


기존 RecyclerView 사고

우리는 오랫동안 이런 구조에 익숙했습니다.

RecyclerView
 └ Adapter
     └ ViewHolder

그리고 주요 고민은:

  • View 재사용
  • notifyDataSetChanged()
  • partial update
  • payload
  • ViewHolder 최적화

였습니다.

즉:

리스트를 어떻게 효율적으로 갱신할까?

에 집중했습니다.


Compose 방식

Compose에서는:

LazyColumn {

    items(users) { user ->

        Text(user.name)
    }
}

처럼 작성합니다.

여기서 핵심은:

“어떻게 갱신할까?”

가 아니라

“현재 데이터가 무엇인가?”

입니다.


사고 흐름 비교

기존 Android

데이터 변경
→ Adapter notify
→ View 갱신

Compose

State 변경
→ Recomposition
→ UI 재계산

Compose에서는:

UI 갱신을 직접 지시

하지 않습니다.

상태가 바뀌면 UI가 자동으로 다시 계산됩니다.


Fragment Navigation 사고 변화

이 부분도 매우 중요합니다.


기존 Android Navigation

우리는 오랫동안:

Activity
 └ Fragment A
      └ Fragment B

구조에 익숙했습니다.

그리고:

fragmentManager.beginTransaction()

중심으로 사고했습니다.

즉:

“화면 객체를 이동”

하는 개념입니다.


Compose Navigation 사고

Compose에서는:

현재 App State가 무엇인가?

관점으로 접근합니다.

예:

sealed class Screen {

    object Home : Screen()

    object Detail : Screen()
}
when(screen) {

    is Screen.Home -> HomeScreen()

    is Screen.Detail -> DetailScreen()
}

즉:

화면 이동

보다

현재 화면 상태 변화

에 가깝습니다.


화면 회전 대응 사고 변화

Android 개발자들이 오랫동안 고생한 부분입니다.


기존 Android

회전 시:

onSaveInstanceState()

를 많이 다뤘습니다.

Lifecycle 중심 사고였습니다.


Compose

Compose에서는:

rememberSaveable

같은 상태 보존 메커니즘을 사용합니다.

예:

var text by rememberSaveable {
    mutableStateOf("")
}

즉 사고가:

Lifecycle 대응

에서

상태 보존 전략

으로 이동합니다.


비동기 처리 사고 변화

이 변화도 매우 큽니다.


기존 Android

기존에는:

  • callback
  • listener
  • handler
  • LiveData observer

중심이었습니다.

즉:

Event 처리

가 핵심이었습니다.


Compose

Compose에서는:

val uiState by
    viewModel.uiState.collectAsState()

처럼:

상태 Stream을 관찰

합니다.

예:

when(uiState) {

    is Loading -> LoadingUI()

    is Success -> SuccessUI()

    is Error -> ErrorUI()
}

즉:

비동기 이벤트 처리

보다

Reactive State Flow

가 중심이 됩니다.


Compose의 핵심은 UI가 아니다

많은 사람들이 Compose를:

새로운 UI Toolkit

으로만 생각합니다.

하지만 실제 핵심은:

Data Flow Architecture 변화

입니다.


기존 Android 사고 vs Compose 사고

기존 Android Compose
View 조작 State 선언
notifyDataSetChanged 자동 recomposition
Fragment 이동 Screen state
callback 중심 reactive stream 중심
imperative UI declarative UI
mutable object immutable state 지향
lifecycle callback state-driven UI

Android 전문가가 처음 헷갈리는 이유

Android 경험이 깊을수록 처음엔 Compose를 보며:

“이건 그냥 DSL UI 아닌가?”

처럼 느끼기 쉽습니다.

왜냐하면 처음엔:

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

같은 문법만 보이기 때문입니다.

하지만 실제 핵심은:

UI = f(state)

라는 철학입니다.

즉:

“UI를 함수처럼 생각하기”

입니다.


Compose를 이해하는 가장 중요한 문장

Compose를 이해하는 가장 중요한 문장은 이것입니다.

현재 상태가 바뀌면
UI는 다시 계산된다.

Compose 개발은 결국:

상태 흐름을 설계하는 작업

에 가깝습니다.


실전에서 가장 추천하는 연습

Compose 학습에서 가장 중요한 건:

State 흐름 체감

입니다.

그래서 단순 Counter보다:

  • 로그인 화면
  • 검색 리스트
  • 실시간 대시보드
  • 채팅 UI
  • 운전 점수 Dashboard

같은 예제가 훨씬 좋습니다.


예를 들어 운전 Dashboard는:

  • GPS Stream
  • 속도 변화
  • 위험 이벤트
  • 리스트
  • Flow
  • recomposition
  • Lifecycle
  • Hybrid UI

전부 경험할 수 있습니다.


마무리

Compose의 진짜 변화는:

XML → Kotlin

이 아닙니다.

실제로는:

View 중심 사고
→
State 중심 사고

로의 이동입니다.

그리고 이 변화는:

  • UI 구조
  • Architecture
  • Data Flow
  • Navigation
  • 비동기 처리
  • 상태 관리

전체를 바꿉니다.

그래서 Compose를 제대로 배우려면:

“Composable 문법”

보다

“상태 흐름을 어떻게 설계할까?”

를 먼저 고민해야 합니다.

다음 글에서는:

“Compose에서 반드시 이해해야 하는 핵심 개념들”

을 실제 코드와 함께 정리해보겠습니다.

— Compose는 XML의 대체제가 아니다

Android 개발을 오래 해온 사람이라면 자연스럽게 이런 흐름에 익숙합니다.

Activity
 └ XML Layout
     └ View(Button, TextView, RecyclerView ...)

그리고 우리는 오랫동안 다음과 같은 방식으로 UI를 개발해 왔습니다.

textView.text = "Hello"
button.isEnabled = false
recyclerView.adapter.notifyDataSetChanged()

 

즉:

“화면 객체(View)를 직접 조작하는 방식”

입니다.

 

하지만 Jetpack Compose는 이 접근 자체를 바꾸려고 등장했습니다.

Compose는 단순히:

XML → Kotlin

변환이 아닙니다.

실제로는:

Control 중심 UI
→
State 중심 UI

로의 패러다임 이동에 가깝습니다.


기존 Android UI 시스템의 구조

전통적인 Android UI 구조는 아래와 같았습니다.

Activity
 └ XML Layout
      └ View Tree

예를 들어:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
    }
}

여기서:

Activity의 역할

  • 화면 생명주기 관리
  • Intent 처리
  • 권한 처리
  • Navigation 연결
  • Window 관리

즉:

Android OS와 연결되는 “화면 컨테이너”

역할을 했습니다.


View/XML의 역할

실제 UI를 그리는 역할입니다.

Button
TextView
RecyclerView
ConstraintLayout

같은 객체(View)를 생성하고 조작했습니다.

예:

button.visibility = View.GONE

즉:

“UI 객체를 직접 수정하는 방식”

입니다.


왜 이 방식이 어려워졌을까?

Android 앱이 커질수록 문제가 생기기 시작했습니다.

예를 들어:

  • 화면 상태 증가
  • 비동기 처리 증가
  • RecyclerView 복잡도 증가
  • Lifecycle 문제
  • 화면 회전 대응
  • Fragment 관리 복잡도
  • 상태 동기화 문제

특히 현대 앱은:

실시간 데이터
+
Reactive Stream
+
비동기 이벤트

가 매우 많아졌습니다.

 

예:

  • 채팅
  • 지도
  • 뉴스 피드
  • 실시간 운전 정보
  • 스트리밍 UI
  • AI 응답 UI

이런 구조에서 “View를 직접 조작”하는 방식은 점점 유지보수가 어려워졌습니다.


Compose의 핵심 철학

Compose는 이 문제를 해결하기 위해 등장했습니다.

핵심 개념은 단 하나입니다.

UI = f(state)

 

즉:

현재 상태(State)가 무엇인가?

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


예를 들어 기존 방식은:

button.isEnabled = false

처럼 UI를 직접 수정합니다.


Compose에서는:

Button(
    enabled = id.isNotBlank()
)

처럼:

“현재 상태를 선언”

합니다.

 

Compose는 상태를 보고 화면을 다시 그립니다.


Compose 시대의 구조

Compose에서는 구조가 이렇게 바뀝니다.

Activity
 └ Compose Runtime
      └ Composable Functions

예:

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            Greeting("Android")
        }
    }
}
@Composable
fun Greeting(name: String) {
    Text("Hello $name")
}

Activity는 사라진 걸까?

많이 오해하는 부분입니다.

Compose는 Activity를 대체한 것이 아닙니다.

여전히 Activity는 중요합니다.


Activity의 역할

Compose 시대에도 Activity는:

  • Lifecycle
  • Permission
  • Intent
  • Navigation Root
  • System UI
  • Window 관리

등을 담당합니다.

즉:

Android 시스템과 연결되는 Entry Point

역할은 그대로 유지됩니다.


Compose의 역할

Compose는:

  • 상태(State)를 입력받아
  • UI를 선언하고
  • 상태가 바뀌면 다시 그림(Recomposition)

을 담당합니다.

즉:

State → UI

변환 엔진에 가깝습니다.


Compose의 진짜 변화

많은 사람들이 처음 Compose를 보면 이렇게 생각합니다.

“XML 대신 Kotlin 쓰는 거네?”

하지만 실제 핵심은 다릅니다.

Compose는:

객체(View) 중심 UI

함수(Function) 중심 UI

로 바꾼 것입니다.


기존 View 시스템

기존 Android는:

Button 객체 생성
→ 속성 변경
→ invalidate()
→ redraw

방식이었습니다.

즉:

Mutable Object Tree 기반 UI

입니다.


Compose 시스템

Compose는:

현재 상태 → UI 함수 실행 → 화면 생성

방식입니다.

즉:

선언형(Declarative) UI

입니다.


Recomposition이라는 개념

Compose에서 매우 중요한 개념이 있습니다.

Recomposition

상태(State)가 바뀌면 필요한 부분만 다시 그리는 메커니즘입니다.

예:

var count by remember {
    mutableStateOf(0)
}
Text("$count")

count 값이 바뀌면 Text 부분만 다시 계산됩니다.

Compose는:

State 변화
→ 필요한 UI만 재계산

하는 구조입니다.


Compose가 중요한 이유

Compose의 진짜 의미는 단순 UI Toolkit 변경이 아닙니다.

사실상 Android UI Architecture 전체가 바뀌고 있습니다.


기존 사고

어떻게 View를 조작할까?

Compose 사고

현재 상태를 어떻게 표현할까?

이 변화 때문에 다음 개념들이 중요해졌습니다.

  • State Hoisting
  • Unidirectional Data Flow
  • Reactive UI
  • Flow/StateFlow
  • Immutable State
  • MVI Architecture

Compose는 단순 UI 라이브러리가 아니라:

State 중심 Architecture를 위한 UI 시스템

에 가깝습니다.


현대 Android 구조

요즘 Android 앱은 보통 이렇게 구성됩니다.

MainActivity
 └ NavHost
      └ Screen Composables
           └ UI Components

그리고 데이터 흐름은:

Repository
   ↓
ViewModel
   ↓
StateFlow
   ↓
Compose UI

형태로 연결됩니다.

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


Android 개발자에게 중요한 사고 전환

Compose를 배우며 가장 중요한 변화는 이것입니다.


기존 방식

textView.text = "Hello"

즉:

UI 객체를 직접 수정


Compose 방식

Text(text = message)

즉:

현재 상태를 선언


Compose 학습의 핵심은:

View를 어떻게 만들까?

보다

상태 흐름을 어떻게 설계할까?

입니다.


마무리

Compose는 단순히:

XML 대신 Kotlin

이 아닙니다.

실제로는:

Control 중심 UI
→
State 중심 UI

로의 전환입니다.

그리고 이 변화는 단순 UI 기술 변경이 아니라:

  • Architecture 변화
  • Data Flow 변화
  • 상태 관리 방식 변화
  • Android 개발 사고방식 변화

까지 포함합니다.

그래서 Compose를 제대로 이해하려면:

“UI를 어떻게 그릴까?”

보다

“현재 상태를 어떻게 표현할까?”

를 먼저 고민해야 합니다.

다음 글에서는:

“Android 개발자의 사고는 Compose에서 어떻게 바뀌는가?”

를 실제 예제를 통해 살펴보겠습니다.

+ Recent posts