안드로이드 개발을 하면서 오랫동안 XML + Fragment 기반으로 개발을 해왔다.
이번 Compose를 공부하면서 느낀 건 단순히 UI 작성 방식이 바뀐 게 아니라 앱을 구성하는 방식 자체가 바뀌고 있다는 점이었다.

 

공부는 excited

1. 화면 구성: Fragment → Composable

예전 안드로이드에서 화면은 Fragment + XML이었다.

FragmentManager로 Transaction 날리고, backstack 관리하고, 생명주기 꼬이면 크래시 터지고 난리부르스였다.

조금만 복잡해져도 "이 Fragment 지금 attach 상태 맞나?" 같은 디버깅을 꽤 많이 했던 기억이 있다.

 

Compose에서는 화면이 @Composable 함수다.

상태(State)가 바뀌면, 그 상태를 사용하는 Composable이 다시 호출되면서 UI가 다시 그려진다.

그리고 Navigation도 Fragment가 아니라 Route 기반으로 동작한다.

home
detail/123
profile/42
 

이런 문자열 주소를 기준으로 화면 함수가 교체된다.

 

물론 현실에서는 Fragment가 완전히 사라지진 않는다.
BottomSheetDialogFragment 같은 라이브러리도 아직 Fragment 기반이고, 기존 프로젝트에서는 레거시 코드가 섞여 있기 때문이다.

그래서 정확히 말하면 Fragment가 사라졌다기보다, 의존성이 크게 줄어드는 방향으로 바뀌고 있다.

 

공부하면서 진짜 Fragment 영역이 줄어든 거는 너어어어어어무 편하고 좋다.

2. 로컬 저장소: SharedPreferences → DataStore

DataStore는 코루틴 + Flow 기반 저장소다.

데이터를 단순히 읽어오는 게 아니라, Flow로 데이터 흐름을 구독하는 구조다.

즉, 값이 바뀌면 UI가 자동으로 다시 그려진다.

 

SharedPreferences처럼

 
값 변경
→ 다시 읽기
→ UI 반영

이런 코드를 직접 작성할 필요가 없다.

 

앱 구동할 때, 저장해서 쓰는 value들도 훨씬 편하고 타이밍 관리가 편해진 거 같다.

3. 이벤트 전달: Broadcast → SharedFlow

예전에 앱 내부 이벤트 전달할 때
LocalBroadcastManager나 PendingIntent 같은 걸 쓰기도 했다.

근데 이 구조는

  • 인텐트 파싱 귀찮고
  • 등록/해제 관리 어렵고
  • 잘못하면 메모리 누수

문제가 꽤 많았다.

요즘은 대부분 Flow 기반 이벤트로 바뀌고 있다.

대표적으로

  • SharedFlow
  • Channel

차이는 단순하다.

예전은 "이 이벤트를 방송한다"

지금은 "이 데이터 흐름을 구독한다"

 

이 개념 차이다.

4. 리스트 구현: RecyclerView → LazyColumn

RecyclerView 만들 때 항상 느끼던 게 있다.

 

Adapter / ViewHolder / DiffUtil

 

파일이 기본 2~3개는 생긴다. 그 보일러플레이트 코드가 꽤 부담이었다. 그리고 나중가면 헷갈려서 끙끙 앓던 기억이 있다.

Compose에서는 LazyColumn 하나로 끝난다.

어댑터가 없다.

리스트도 그냥 함수 안에서 선언한다.

그리고 DiffUtil이 하던 역할은
아이템의 key가 대신한다.

데이터가 바뀌면 key를 기준으로 변경된 부분만 Recomposition된다.

 

RecyclerView Adapter 만들던 시절 생각하면
아직도 이게 함수 하나로 끝난다는 게 좀 신기하다.

5. 딥링크: 수동 매칭 → 자동 라우팅

예전에 Firebase 딥링크 처리할 때는
Activity에서 URL 받고

  • 파싱하고
  • 파라미터 꺼내고
  • 맞는 Fragment 찾아서
  • 트랜잭션 날리고

이걸 전부 수동으로 처리했다.

 

Navigation Compose에서는 NavHost에 딥링크만 등록하면 된다.

그러면 시스템이 알아서 해당 Composable 화면을 실행한다.

 

Notification이나 WorkManager 같은 시스템 도구는 그대로 쓰지만
화면 연결 구조는 딥링크 + Navigation으로 훨씬 단순해진다.

 

내가 쓰던 방식이 이제는 구시대 방식인거를 깨닫고 공부를 하는데, 선언형 UI 구성이라 react랑 비슷하다는 생각이 든다.

UI 선언 JSX @Composable 함수
로컬 상태 useState remember { mutableStateOf() }
상태 유지 (리렌더 생존) useRef remember
상태 유지 (새로고침 생존) 없음 (localStorage 직접) rememberSaveable
전역 상태 Zustand, Redux ViewModel + StateFlow
서버 상태 / 비동기 React Query ViewModel + Repository + Flow
리렌더 최소화 useMemo, React.memo derivedStateOf, remember 람다 안정화
사이드이펙트 useEffect LaunchedEffect, SideEffect
Context 전달 useContext CompositionLocalProvider
라우팅 React Router Navigation Compose
리스트 렌더링 Array.map() LazyColumn
DiffUtil (리스트 최적화) key prop key 파라미터 (동일함)
스타일링 CSS / Tailwind Modifier
컴포넌트 재렌더 조건 props / state 변경 State 변경 → Recomposition

 

react 공부했던게 여기서 이렇게 쓰일 줄은 몰랐는데, 좋다 히히

 

+ Recent posts