— Compose는 UI Toolkit이 아니라 패러다임 전환이다

Compose를 처음 접하면 보통은 이렇게 생각하기 쉽습니다.

“XML 대신 Kotlin으로 UI 만드는 기술”

실제로 처음 보이는 것도:

Text()
Button()
Column()

같은 UI 함수들입니다.

그래서 처음에는:

"새로운 UI DSL"

정도로 느껴질 수 있습니다.

하지만 Compose를 조금 깊게 사용하기 시작하면 점점 다른 느낌이 옵니다.


Compose를 쓰며 느끼는 변화

어느 순간부터 개발 흐름이 바뀌기 시작합니다.

예전에는:

View를 어떻게 조작할까?

를 고민했다면,

Compose에서는:

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

를 고민하게 됩니다.

그리고 이 변화는 단순 UI 기술 변경이 아닙니다.

실제로는:

  • Architecture 변화
  • Data Flow 변화
  • 상태 관리 방식 변화
  • Navigation 사고 변화
  • UI 설계 방식 변화

까지 이어집니다.


Android UI는 원래 어떤 구조였을까

Android의 전통적인 UI 시스템은 기본적으로:

Mutable Object Tree

기반이었습니다.

즉:

View 객체 생성
→ 속성 수정
→ invalidate()
→ redraw

구조입니다.

예:

textView.text = "Hello"
button.visibility = View.GONE

우리는 오랫동안:

“화면 객체를 직접 수정”

하는 방식으로 UI를 개발했습니다.


이 방식의 장점

이 구조는 매우 직관적입니다.

특히 Android 초기에는:

  • 단순 화면
  • 로컬 상태
  • 적은 비동기 처리

환경에서는 잘 동작했습니다.

그리고 Android Framework는:

  • Lifecycle
  • View hierarchy
  • Adapter
  • Fragment

등을 중심으로 발전했습니다.


하지만 앱이 복잡해졌다

문제는 앱 구조가 점점 복잡해졌다는 것입니다.

현대 앱은:

  • 실시간 데이터
  • streaming UI
  • AI 응답
  • 지도
  • reactive stream
  • 멀티 디바이스
  • 비동기 이벤트

가 매우 많아졌습니다.

예:

채팅
뉴스 피드
실시간 운전 정보
AI Assistant
Video Streaming

이런 구조에서:

View를 직접 수정하는 방식

은 점점 복잡해졌습니다.


Compose가 바꾼 것

Compose는 이 흐름을 바꾸기 시작했습니다.

핵심 철학은 단 하나입니다.

UI = f(state)

즉:

“현재 상태를 기반으로 UI를 계산한다”

입니다.


중요한 변화

Compose는:

UI 객체를 조작

하는 것이 아니라

상태를 선언

합니다.


예:

기존 Android

button.isEnabled = true

Compose

Button(
    enabled = canSubmit
)

Compose는:

현재 상태가 무엇인가?

만 보고 UI를 다시 계산합니다.


Compose의 진짜 핵심

많은 사람들이 Compose의 핵심을:

Declarative UI

라고 말합니다.

물론 맞는 말입니다.

하지만 실제 더 중요한 변화는:

Control 중심 Architecture
→
State 중심 Architecture

입니다.


기존 Android 사고

기존 Android에서는:

화면을 어떻게 조작할까?

가 중심이었습니다.


Compose 사고

Compose에서는:

현재 상태를 어떻게 모델링할까?

가 중심이 됩니다.


그래서 Flow와 Compose가 잘 맞는다

Compose를 쓰다 보면 자연스럽게 이런 구조로 갑니다.

Repository
   ↓
Flow
   ↓
ViewModel
   ↓
StateFlow
   ↓
Compose UI

왜냐하면 Compose는:

상태(State)를 기반으로
UI를 다시 계산하는 시스템

이기 때문입니다.


Compose는 함수형 UI에 가깝다

Compose는 결국:

UI를 함수처럼 생각하는 방식

입니다.

즉:

UI = f(state)

입니다.


기존 View 시스템

기존에는:

mutable object

를 직접 수정했습니다.


Compose 시스템

Compose에서는:

현재 상태 → 함수 실행 → UI 계산

입니다.

즉:

UI가 “객체”보다 “계산 결과”에 가까워집니다.


React / SwiftUI / Flutter와의 공통점

흥미로운 점은:

  • React
  • SwiftUI
  • Flutter
  • Compose

모두 비슷한 방향으로 이동하고 있다는 것입니다.

공통 철학은:

State-driven UI

입니다.


왜 이런 흐름이 생겼을까

현대 UI는:

  • 비동기 이벤트
  • 실시간 데이터
  • 네트워크 상태
  • 사용자 상호작용

이 계속 변화합니다.

즉:

UI가 "고정된 화면"

이 아니라:

계속 변화하는 상태의 흐름

이 되었습니다.

그래서:

상태를 중심으로
UI를 계산하는 구조

가 더 자연스러워졌습니다.


Compose를 배우며 다시 보이는 Android Architecture

Compose를 깊게 사용하다 보면 기존 Android Architecture도 다시 보이기 시작합니다.

예:

  • Fragment는 상태 컨테이너처럼 보이고
  • RecyclerView는 state rendering 문제처럼 보이고
  • Navigation은 route state처럼 보이고
  • Lifecycle도 state transition처럼 보입니다.

즉:

Android Architecture 전체를
상태 흐름 관점으로 다시 보게 된다

는 변화가 생깁니다.


Compose가 중요한 이유

Compose의 진짜 의미는:

XML 제거

가 아닙니다.

실제로는:

Android 개발 사고방식 자체 변화

에 가깝습니다.


Android 경험자는 왜 유리한가

기존 Android 경험이 깊다면:

  • Lifecycle
  • Threading
  • Performance
  • Navigation
  • Multimedia
  • Reactive stream

경험이 이미 있기 때문에 Compose에서도 강점이 있습니다.

특히:

  • Flow
  • Coroutine
  • 상태 변화
  • 이벤트 흐름

에 익숙하다면 Compose를 훨씬 빠르게 이해할 수 있습니다.


하지만 가장 어려운 변화

Compose에서 가장 어려운 것은 결국 이것입니다.

View 중심 사고를
버리는 것

입니다.


Compose를 잘한다는 것

Compose를 잘한다는 것은:

Fancy UI를 만드는 것

보다:

상태 흐름을 명확하게 설계하는 것

에 가깝습니다.


앞으로 Android는 어떻게 될까

개인적으로 Compose 이후 Android 개발은 점점:

Reactive
+
State-driven
+
Function-oriented

방향으로 갈 가능성이 높다고 생각합니다.

그리고 이는 단순 Android만의 흐름이 아닙니다.

전체 UI 개발 생태계가 같은 방향으로 이동하고 있습니다.


Compose와 AI 시대

흥미로운 부분은 Compose의 구조가 AI 시대와도 잘 맞는다는 점입니다.

왜냐하면 AI 시스템 역시:

상태(State)
+
Event
+
Stream
+
Reactive Flow

중심으로 움직이기 때문입니다.

예를 들어:

  • Streaming Text
  • Tool Execution State
  • AI Agent Workflow
  • Real-time Suggestion UI

등은 모두:

State 변화 기반 UI

와 잘 맞습니다.


Compose를 한 문장으로 정리하면

Compose는 단순히:

새로운 Android UI Toolkit

이 아닙니다.

실제로는:

상태(State)를 중심으로
UI와 Architecture를 다시 설계하는 방식

에 가깝습니다.


시리즈를 마무리하며

이번 시리즈에서는:

  1. Compose는 왜 등장했는가
  2. Android 개발자의 사고는 어떻게 바뀌는가
  3. Compose 핵심 개념
  4. 예제로 배우는 Compose
  5. 실무 Compose Architecture
  6. Compose를 배우며 다시 생각한 Android Architecture

흐름으로 Compose를 정리해보았습니다.

결국 Compose의 핵심은:

UI를 어떻게 만들까?

보다

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

에 있습니다.

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

Android 개발 사고방식 자체의 변화

라고 볼 수 있습니다.

OpenClaw의 ACP(Agent Client Protocol)를 사용하면 OpenClaw에서 Claude Code를 외부 코딩 에이전트로 실행할 수 있습니다. 전체 과정은 다음 네 단계입니다.

  1. ACPX 플러그인 설치 및 활성화
  2. 전역 ACP 설정
  3. Claude Code 설치 및 인증
  4. ACP 연결 검증

1. ACPX 플러그인 설치 및 활성화

OpenClaw Gateway에서 다음 명령을 실행합니다.

openclaw plugins install @openclaw/acpx
openclaw config set plugins.entries.acpx.enabled true

설정 파일에는 다음 항목이 생성되거나 활성화됩니다.

{
  "plugins": {
    "entries": {
      "acpx": {
        "enabled": true
      }
    }
  }
}

ACPX는 OpenClaw가 Claude Code, Codex, Gemini CLI 등의 ACP harness를 실행할 때 사용하는 공식 런타임 플러그인입니다. Claude용 ACP 어댑터는 첫 실행 시 자동으로 준비되므로 별도의 claude-agent-acp 패키지를 직접 설치할 필요는 없습니다.

2. 전역 ACP 설정

openclaw.json의 최상위에 다음 acp 블록을 추가합니다.

{
  "acp": {
    "enabled": true,
    "dispatch": {
      "enabled": true
    },
    "backend": "acpx",
    "defaultAgent": "claude",
    "allowedAgents": [
      "claude",
      "gemini"
    ],
    "maxConcurrentSessions": 8
  }
}

각 항목의 의미는 다음과 같습니다.

  • enabled: ACP 기능 전체 활성화
  • dispatch.enabled: ACP 세션 자동 dispatch 허용
  • backend: ACP 백엔드로 acpx 사용
  • defaultAgent: 기본 harness를 Claude로 지정
  • allowedAgents: 사용할 수 있는 ACP harness 목록
  • maxConcurrentSessions: 동시에 실행할 수 있는 ACP 세션 수

Claude만 사용할 경우에는 다음처럼 간단히 구성해도 됩니다.

"allowedAgents": ["claude"]

별도의 OpenClaw agent를 Claude ACP 전용으로 고정하지 않는다면 agents.list 설정은 필요하지 않습니다. 전역 ACP 설정만으로 필요할 때 Claude를 호출할 수 있습니다.

3. Claude Code 설치 및 인증

Claude Code가 Gateway가 실행되는 호스트에 설치되어 있어야 합니다.

npm install -g @anthropic-ai/claude-code

설치 상태를 확인합니다.

claude --version
claude doctor

처음 실행하면 인증 절차가 진행됩니다.

claude

화면의 안내에 따라 Anthropic Console 또는 Claude Pro/Max 계정으로 로그인합니다. ACP는 OpenClaw의 인증을 대신하지 않으므로, Claude Code 인증은 반드시 Gateway 호스트에서 별도로 완료해야 합니다.

4. ACP 사용 검증

먼저 Gateway에서 ACP 백엔드 상태를 확인합니다.

/acp doctor

정상이라면 ACP 백엔드가 enabled/healthy 상태로 표시됩니다.

다음 검증 프롬프트를 입력합니다.

OpenClaw ACP 연결 검증을 수행해 주세요.

1. 현재 ACP harness 이름을 Claude Code라고 답하세요.
2. 현재 작업 디렉터리의 절대 경로를 알려 주세요.
3. 현재 세션이 ACP를 통해 실행되었다고 명시해 주세요.
4. 파일을 생성하거나 수정하지 말고, 명령 실행도 하지 마세요.
5. 마지막 줄에 정확히 "ACP 연결 검증 완료"라고 출력해 주세요.

다음과 같은 응답을 받으면 기본 연결이 정상입니다.

Claude Code ACP 세션입니다.
현재 작업 디렉터리: /...
ACP를 통해 실행되었습니다.
ACP 연결 검증 완료

문제 발생 시 확인 순서

/acp doctor
  1. ACPX 플러그인이 설치·활성화되어 있는지 확인
  2. acp.enabledtrue인지 확인
  3. acp.allowedAgentsclaude가 포함되어 있는지 확인
  4. Gateway 호스트에서 claude --version이 동작하는지 확인
  5. Claude Code 인증이 완료되어 있는지 확인
  6. cwd로 지정한 작업 디렉터리가 실제로 존재하는지 확인
  7. 설정 변경 후 Gateway를 재시작

설정 변경 후에는 Gateway를 재시작해야 합니다.

openclaw gateway restart

참고 문서:

주의할 점은 Claude Code 설치와 ACPX 플러그인 설치가 서로 다른 단계라는 것입니다. Claude Code는 실제 harness와 인증을 제공하고, ACPX는 OpenClaw가 그 harness를 ACP 세션으로 실행하도록 연결하는 역할을 합니다.

— 대규모 Android 앱에서 Compose 구조화하기

Compose를 처음 배울 때는 보통 이런 흐름으로 시작합니다.

Text()
Button()
Column()

그리고 Counter, 로그인 화면 같은 예제를 만들며:

State → Recomposition

을 이해하게 됩니다.

하지만 실제 프로젝트로 들어가면 곧 이런 고민이 생깁니다.

  • 상태(State)는 어디에 둬야 하지?
  • ViewModel은 어디까지 담당해야 하지?
  • Navigation 구조는 어떻게 가져가야 하지?
  • Flow와 Compose는 어떻게 연결해야 하지?
  • Compose와 기존 View는 어떻게 섞어야 하지?
  • 대규모 앱에서 recomposition은 어떻게 관리하지?

특히 Android 경험이 많을수록:

“Compose를 어디에 붙여야 하는가?”

보다

“Compose 시대에는 Architecture가 어떻게 바뀌는가?”

가 더 중요해집니다.

이번 글에서는 실무 Compose Architecture를 중심으로 정리해보겠습니다.


Compose Architecture의 핵심 변화

Compose의 진짜 변화는 UI Toolkit 자체보다:

Data Flow Architecture 변화

에 있습니다.


기존 Android 구조

기존 Android는 보통:

Activity
 └ Fragment
     └ View

구조였습니다.

그리고:

  • Fragment lifecycle
  • View lifecycle
  • callback
  • listener
  • adapter

중심으로 설계했습니다.


Compose 구조

Compose에서는 보통 이렇게 갑니다.

Activity
 └ NavHost
      └ Screen Composables
           └ UI Components

그리고 데이터 흐름은:

Repository
   ↓
Flow
   ↓
ViewModel
   ↓
StateFlow
   ↓
Compose UI

입니다.

즉:

Reactive State Architecture

가 중심이 됩니다.


실무에서 가장 중요한 구조

Compose 실무에서 가장 중요한 것은:

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

입니다.

즉:

  • 상태(State)는 ViewModel
  • 데이터 흐름은 Flow
  • UI는 상태 렌더링

역할로 분리됩니다.


추천 구조

가장 추천되는 기본 구조는 아래입니다.

Repository
   ↓
Flow<Data>
   ↓
ViewModel
   ↓
UiState
   ↓
Compose UI

왜 이런 구조가 중요한가?

Compose는:

State 변화 → Recomposition

기반으로 동작합니다.

따라서:

상태 흐름이 명확할수록
Architecture가 단순해진다

는 특징이 있습니다.


실무 예제 구조

예를 들어 뉴스 화면.


Repository

class NewsRepository {

    fun observeArticles(): Flow<List<Article>> {
        ...
    }
}

Repository는:

  • API
  • DB
  • Cache

등 데이터 소스를 관리합니다.


ViewModel

class NewsViewModel(
    private val repository: NewsRepository
) : ViewModel() {

    val uiState =
        repository.observeArticles()
            .map {
                NewsUiState.Success(it)
            }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5000),
                initialValue = NewsUiState.Loading
            )
}

ViewModel은:

  • 상태 보관
  • 상태 변환
  • 비즈니스 로직

을 담당합니다.


Compose UI

@Composable
fun NewsScreen(
    viewModel: NewsViewModel = viewModel()
) {

    val state by
        viewModel.uiState.collectAsStateWithLifecycle()

    when(state) {

        is Loading -> LoadingUI()

        is Success -> ArticleList()

        is Error -> ErrorUI()
    }
}

Compose는:

현재 상태를 렌더링

만 합니다.


실무 Compose에서 가장 중요한 개념

1. UiState 모델링

Compose에서는 UI 상태를 명확히 정의하는 것이 매우 중요합니다.

추천:

sealed interface UiState {

    object Loading : UiState

    data class Success(...) : UiState

    data class Error(...) : UiState
}

왜 중요한가?

이 구조를 쓰면:

현재 UI 상태가 명확해진다

는 장점이 있습니다.

Compose는 상태 기반 시스템이므로:

상태 모델링 자체가
Architecture가 된다

고 볼 수 있습니다.


2. State Hoisting

실무에서 매우 중요합니다.


좋지 않은 구조

Composable 내부에서
상태를 모두 관리

추천 구조

상태는 ViewModel
UI는 렌더링

예:

TextField(
    value = query,
    onValueChange = onQueryChanged
)

Composable은:

  • 상태를 보여주고
  • 이벤트를 위로 전달

만 합니다.


장점

이 구조는:

  • Preview 용이
  • 테스트 쉬움
  • 재사용성 증가
  • recomposition 추적 쉬움

장점이 있습니다.


3. Unidirectional Data Flow (UDF)

Compose와 가장 잘 맞는 구조입니다.


흐름

User Event
    ↑
Compose UI
    ↓
UiState
    ↓
ViewModel

핵심

State는 아래로
Event는 위로

흐릅니다.

Compose는 이 구조를 전제로 설계된 느낌에 가깝습니다.


4. Navigation Architecture

Compose 시대에는:

Single Activity Architecture

가 일반적입니다.


구조

MainActivity
 └ NavHost
      └ Screens

기존 Android와 차이

기존:

Fragment 객체 이동

Compose:

현재 route 상태 변경

입니다.


예제

NavHost(
    navController = navController,
    startDestination = "home"
)

실무 포인트

중요한 것:

  • nested graph
  • argument
  • deep link
  • back stack

입니다.


5. Flow + Compose 조합

Compose와 가장 잘 맞는 데이터 흐름은:

StateFlow

입니다.


추천 패턴

val uiState by
    viewModel.uiState.collectAsStateWithLifecycle()

collectAsStateWithLifecycle가 중요한 이유

실무에서는 lifecycle 문제가 매우 중요합니다.

추천:

collectAsState()

보다

collectAsStateWithLifecycle()

사용.


이유

Lifecycle inactive 상태에서:

  • 불필요한 collect 감소
  • 메모리 누수 감소
  • background 처리 안정성 증가

효과가 있습니다.


6. Compose와 기존 View 혼합

실무에서 매우 중요합니다.

현실적으로 대부분 앱은:

Compose Only

가 아닙니다.

실제로는:

Compose + 기존 View 혼합

구조가 훨씬 많습니다.


AndroidView

예:

AndroidView(
    factory = {
        PlayerView(it)
    }
)

자주 섞이는 것

특히:

  • ExoPlayer
  • CameraX
  • WebView
  • MapView
  • VideoView

등은 여전히 View 기반이 많습니다.


중요한 사고

Compose는:

기존 Android를 버리는 기술

이 아니라:

기존 Android 위에
선언형 UI를 얹는 구조

에 가깝습니다.


7. Recomposition 최적화

실무에서는 성능 문제가 중요합니다.


자주 발생하는 문제

불필요한 recomposition

중요한 포인트

immutable state 사용

추천:

data class UiState(...)

stable object 유지


key 지정

items(
    list,
    key = { it.id }
)

remember 사용

remember { ... }

Compose 성능의 핵심

Compose 성능 최적화의 본질은:

어떻게 redraw 할까?

보다:

어떻게 state 변화를 최소화할까?

에 가깝습니다.


실무에서 추천하는 폴더 구조

추천 예시:

ui/
 ├ screens/
 ├ components/
 ├ theme/

data/
 ├ repository/
 ├ remote/
 ├ local/

domain/
 ├ model/
 ├ usecase/

navigation/

viewmodel/

ComposeSample 프로젝트 관점

실제로 ComposeSample에서도 흐름이 잘 드러납니다.

특히:

STEP 1
→ State + Recomposition

STEP 4
→ Flow + ViewModel

STEP 5
→ Navigation

STEP 6
→ Hybrid UI

순서로:

Compose UI
→ Reactive Architecture
→ 실무 구조

로 확장되는 흐름이 매우 좋습니다.


실무에서 Compose를 잘한다는 의미

많은 사람들이:

  • fancy animation
  • custom UI
  • 디자인 시스템

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

하지만 실제 중요한 것은:

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

입니다.


Android 경험자가 특히 강점을 가지는 부분

기존 Android 경험이 깊다면:

  • Lifecycle
  • Threading
  • Multimedia
  • Navigation
  • Performance
  • Reactive stream

경험이 이미 있기 때문에:

Compose에서도 강점을 가질 가능성이 높습니다.

다만 가장 중요한 변화는:

View 중심 사고를
State 중심 사고로 바꾸는 것

입니다.


마무리

Compose 시대의 Android Architecture는 결국:

Reactive State Architecture

로 수렴합니다.

그리고 실무에서는:

Repository
→ Flow
→ ViewModel
→ StateFlow
→ Compose UI

구조가 중심이 됩니다.

Compose를 잘한다는 것은 결국:

“상태 흐름을 얼마나 명확하게 설계할 수 있는가”

에 가까워집니다.

다음 글에서는:

“Compose를 배우며 다시 생각한 Android Architecture”

를 중심으로, Compose가 Android 개발 방식 자체를 어떻게 바꾸고 있는지 조금 더 큰 관점에서 정리해보겠습니다.

+ Recent posts