
"공유 가능"이 "좋은 사용자 경험"을 보장하진 않더라고요. 화면 코드를 다 합칠 수 있게 됐는데도, 저는 일부러 30%를 네이티브로 남겨뒀습니다.
지난 봄부터 석 달 정도, 로직만 공유하던 코틀린 멀티플랫폼(Kotlin Multiplatform) 프로젝트에서 화면까지 욕심을 내봤어요. 결과부터 말씀드리면, 합칠 수 있는 것과 합치는 게 나은 것은 다른 얘기였습니다.
화면 코드까지 공유하려던 진짜 이유
같은 설정 화면을 SwiftUI랑 Compose로 두 번 그리는 게 워낙 비효율이었거든요. 디자인은 하나인데 구현은 둘이니, 스프린트 하나가 통째로 "같은 화면 두 번 만들기"에 들어가는 일이 반복됐어요.
게다가 미세한 차이가 사람을 잡더군요. 패딩 2dp, 폰트 굵기 같은 게 두 플랫폼에서 미묘하게 어긋나서, QA 리포트에 똑같은 항목이 계속 올라왔습니다.
그래서 실험 대상은 인터랙션이 적은 화면으로만 한정했어요. 설정, 약관, 목록처럼 사용자가 휙휙 넘기기만 하는 곳부터요. 결제나 입력이 많은 화면은 일부러 뺐습니다.

iOS 정식 지원은 1.11이 아니라 1.8에서 끝난 얘기
여기서 오해를 하나 풀고 가야겠어요. iOS 정식 지원(Stable)은 1.11이 아니라 1.8.0 버전에서 이미 달성된 것으로 알려져 있어요. 작년 5월쯤 일이지요.
그러니까 1.11.0은 "이제 iOS 됩니다"가 아니라, 이미 되던 걸 더 매끄럽게 다듬은 개선판입니다. 베타 시절 겪던 스크롤 끊김이나 제스처 충돌이 눈에 띄게 줄어서, 60fps 기준으로 체감이 확실히 좋아졌어요.
다만 디버깅은 여전히 불편했어요. Xcode의 시각적 레이아웃 인스펙터로는 Compose가 그린 뷰를 못 까봅니다. 그래서 저는 로그랑 안드로이드 스튜디오(Android Studio)의 Layout Inspector에 의존해서 잡았어요.
Compose Multiplatform 1.11 네이티브 텍스트 입력과 동시 렌더링
1.11에서 제일 눈에 띈 건 실험적인 네이티브 텍스트 입력입니다. iOS 소스셋에 usingNativeTextInput 옵션을 켜고 BasicTextField를 쓰면, iOS 네이티브 UIView 위에서 UITextInput·UIKeyInput 프로토콜로 입력을 처리하거든요.
이게 뭐가 좋냐면, 캐럿 이동이나 더블·트리플 탭 선택, 자동 완성·번역 같은 시스템 메뉴가 네이티브 수준으로 붙습니다. 검색창처럼 입력 경험이 중요한 곳에선 차이가 크게 느껴졌어요.
근데 무조건 켜는 게 답은 아니었습니다. 두 플랫폼 입력 동작을 똑같이 맞추는 게 더 중요하다면, 기존 Compose 입력 방식이 여전히 안정적인 선택지로 보여요. 그래서 저는 검색창 같은 특정 컴포넌트에만 선별 적용했습니다.
나머지 변경점도 짚자면, 동시 렌더링(Concurrent Rendering)이 기본으로 켜져서 렌더링이 별도 스레드로 빠지니까 UI 반응성이 좋아졌어요. 대신 최소 지원 버전이 iOS 13에서 14로 올라갔으니, 구형 기기 비중이 큰 서비스라면 이 부분 먼저 확인하셔야 합니다.

@Preview와 Hot Reload, 그리고 ProMotion 프레임 함정
생산성에서 제일 만족스러웠던 건 공통 소스셋의 @Preview였어요. 안드로이드랑 iOS UI를 한 번에 띄워놓고 보니, 두 번 빌드하던 시간이 절반 가까이 줄었습니다.
Hot Reload로 색상이나 간격을 바로바로 고치면서 디자인 QA를 돌리니까, 확인 → 수정 → 재확인 사이클이 진짜 빨라졌어요.
근데 여기 함정이 하나 숨어 있어요. ProMotion 디스플레이(고주사율) 대응을 위해 Info.plist에 CADisableMinimumFrameDurationOnPhone 키를 꼭 추가해야 합니다. 이걸 빠뜨리면 화면이 60Hz로 묶여서 ProMotion 효과를 못 봐요. 저도 처음에 이거 놓쳐서 한참 헤맸어요.

그래서 30%는 네이티브로 남겨둔 이유
공유 가능하다고 다 공유하진 않았습니다. 결제, 첫 설정 화면처럼 첫인상이 중요한 곳은 SwiftUI로 남겼어요. 머티리얼 디자인의 다이얼로그나 스위치, 화면 전환 효과가 iOS 사용자에겐 어딘가 이질적으로 느껴질 수 있다고 봅니다.
기술적인 비용도 무시 못 했어요. 코틀린은 SwiftUI 뷰나 네이티브 클로저 같은 Swift 전용 API를 직접 못 부릅니다. 중간에 UIViewController랑 Objective-C 호환 코드를 끼워 넣어야 해서, 네이티브 기능을 깊게 엮을수록 복잡도가 확 올라가더라고요.
앱 용량도 늘었습니다. 프로젝트마다 다르지만 제 경우 순수 SwiftUI 앱 대비 약 9MB 정도가 붙었어요. 9MB가 감이 안 오신다면, 고화질 사진 서너 장이 통째로 더 들어간 정도라고 보시면 됩니다. 작아 보여도 다운로드 전환율 따지는 팀엔 충분히 신경 쓰이는 숫자예요.
QA도 마찬가지였습니다. XCTest 같은 자동화 도구에서 Compose 뷰가 제대로 식별되지 않는 경우가 있어서, 접근성 처리랑 테스트 코드에 손이 더 갔습니다.
합칠지 말지, 결국 인터랙션 깊이로 가른다
석 달 굴려보고 제가 잡은 기준은 단순합니다. 화면 공유는 "전부 아니면 전무"가 아니라, 인터랙션 깊이와 네이티브 경험의 중요도를 저울에 올려 범위를 정하는 맞바꿈이에요.
인터랙션이 얕은 화면은 과감히 공유하고, 첫인상과 손맛이 중요한 화면은 네이티브로 남겼습니다. 저는 이 '공유 70, 네이티브 30' 선이 가장 손해가 적었어요.
다 합칠 수 있게 된 지금일수록, 어려운 건 합치는 쪽이 아니라 어디서 멈출지 선을 긋는 쪽입니다. 결국 제가 석 달 동안 배운 건 새 옵션을 켜는 법이 아니라, 30%를 일부러 안 켜고 남겨두는 감각이었습니다.

'Android 개발 > Jetpack Compose' 카테고리의 다른 글
| Compose에서만 죽던 로그인 자동완성, credentialRequest로 살린 배선 일지 (0) | 2026.09.20 |
|---|---|
| 버튼 소리 직접 심었다면 Compose 1.12에서 두 번 울립니다 (1) | 2026.09.19 |
| 값을 화면 깊은 곳까지 파라미터로 줄줄이 내리던 자리 — CompositionLocal 제대로 쓴 일지 (0) | 2026.08.29 |
| Compose 리컴포지션 최적화로 잡은 화면 버벅임 실측기 (0) | 2026.08.21 |
| 비밀번호칸만 자동완성이 안 뜬다면, Compose 1.12 Credential Manager 연동 (0) | 2026.08.16 |