— 대규모 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 개발 방식 자체를 어떻게 바꾸고 있는지 조금 더 큰 관점에서 정리해보겠습니다.
'Android Programming' 카테고리의 다른 글
| 6편 Compose를 배우며 다시 생각한 Android Architecture (0) | 2026.08.26 |
|---|---|
| 4편 예제로 배우는 Android Compose 학습 (0) | 2026.07.29 |
| 3편 Compose에서 반드시 이해해야 하는 핵심 개념들 (1) | 2026.07.15 |
| 2편 Android 개발자의 사고는 Compose에서 어떻게 바뀌는가 (0) | 2026.07.01 |
| 1편: Android Compose는 왜 등장했을까? (0) | 2026.06.10 |