
4.2만 줄짜리 KMP 프로젝트의 재빌드 시간이 21초에서 6.8초로 줄었습니다. 1년 전 같은 코드를 같은 노트북에서 돌렸을 때와 비교하면 사실상 다른 도구라고 봐도 될 정도였어요.
지난 한 주 내내 코틀린(Kotlin) 2.4.0-RC2 를 사이드 프로젝트에 물려놓고 굴려본 결과입니다. 작년 가을부터 Kotlin/JS 로 깔아둔 사이드 프로젝트가 하나 있는데, Wasm 타깃이 Beta 까지 올라왔다고 해서 코틀린 공식 디스코드 채널 친구들 부추김에 한 번 갈아끼워봤거든요. 결과부터 말씀드리면 빌드 속도는 진짜 좋아졌는데, 그 외엔 아직 손이 많이 가더라고요.
Kotlin 2.4 Wasm 증분 컴파일, 21초가 6.8초로
코틀린 2.4.0-RC2 에서 증분 컴파일이 Stable 로 올라오고 기본 활성화됐다고 합니다. Kotlin 2.1.0 에서 실험적으로 처음 들어간 것이 1년 정도 다듬어져 메인 트랙에 합류한 흐름이에요.
제가 직접 측정한 단일 ViewModel 한 줄 수정 후 재빌드는 6.8초였습니다. 같은 머신, 같은 코드를 작년 11월에 잰 기록이 21초였으니까 대략 3배 빨라진 셈입니다. 클린 빌드는 47초로 큰 변화는 없었구요.
다만 모든 수정이 다 빨라지는 건 아니더라고요. expect/actual 선언을 건드리거나 inline 함수 시그니처를 바꾸면 24초로 다시 튀어 올랐습니다. 멀티 모듈 증분도 아직 진행 중이라는 얘기입니다. 한 모듈에서 다른 모듈로 의존이 걸리는 변경은 자주 전체 재컴파일로 떨어졌어요.

빌드 캐시 위치가 안드로이드 개발자가 알아두면 좋은 부분인데요, AGP/Gradle 기존 캐시가 아니라 build/kotlin/ 아래 별도의 KLIB 캐시를 씁니다. 처음에 ./gradlew clean 만 하고 "왜 빠른 빌드가 안 돌아오지" 하다가 KLIB 캐시 자리를 따로 확인하고 나서야 감이 잡혔습니다.
WebAssembly Component Model, 안드로이드 AIDL과 닮은 지점
Component Model 1.0 은 WIT 라는 IDL 로 타입 계약을 잡고, 그 계약을 매개로 언어 간 호출을 묶어주는 구조예요. ESM 모듈 import 처럼 그냥 가져다 쓰는 게 아니라, 안드로이드 AIDL 을 한 번 써본 분이라면 머리로 그려질 비슷한 모양새입니다.

Wasm 3.0(WasmGC 포함) 은 공식 일정상 2025년 9월에 표준화됐고, WASI 0.3.0(네이티브 async I/O 포함) 은 2026년 2월에 릴리스됐습니다. 코틀린 쪽 Component Model 지원은 코틀린 2.4.0-RC2 EAP 에서 실험적으로만 들어와 있는 단계입니다.
저는 KMP 도메인 로직을 .wit 파일로 world 노출해두고, jco transpile 로 웹 번들과 Node CLI 양쪽에서 다시 받아 써봤습니다. JS 쪽 래퍼는 41줄짜리 짧은 파일이 떨어졌어요. AIDL 짜본 손이라면 "아 그 지점이네" 하고 바로 익숙해질 모양인 것 같습니다.
대신 WasmGC 의존성이 발목을 잡습니다. 제가 시도한 시점의 Cloudflare workerd 빌드에선 동작이 안 됐어요. 다만 V8 기반이라 향후 풀릴 여지는 있습니다. JS 백엔드용 Worker 환경에 그대로 올릴 생각이었는데, 그 계획은 일단 접었습니다.
KMP commonMain 코드 공유율을 63%까지 올린 구조
작년 Kotlin/JS 타깃으로 깔았을 때 코드 공유율이 58% 수준이었어요. 이번에 Wasm 타깃을 추가하면서 도메인·UseCase·Repository 전부 commonMain 으로 옮기고, 안드로이드는 Room, Wasm 은 IndexedDB 어댑터로 actual 만 갈아끼웠습니다. 결과적으로 공유율이 63% 까지 올라갔습니다.

Compose Multiplatform 쪽은 리스트·디테일 두 화면만 공유했습니다. 카메라·푸시 같은 플랫폼 전용 영역은 그대로 분리했어요. 욕심내서 다 묶으려다 결국 분기 코드가 더 커지는 걸 KMP 초창기에 한 번 겪었기 때문에, 이번엔 처음부터 선을 그어뒀습니다.
UI 렌더링 체감은 JetBrains 벤치마크가 말하는 "JS 대비 3배" 까지는 잘 모르겠는데, 스크롤 프레임 드롭이 눈에 띄게 줄어서 약 1.8배 정도는 좋아진 것으로 보입니다. 첫 페인트는 큰 차이가 안 났어요.
Kotlin/Wasm 한 주 굴려보며 만난 함정 3가지
1. 번들 크기
Kotlin/Wasm 프로덕션 빌드(browserProductionWebpack)에 wasm-opt -Oz 까지 태웠는데 gzip 기준 1.1MB. 같은 기능의 Kotlin/JS 빌드가 740KB 였으니까 1.5배 정도 큽니다. 1.1MB 가 어느 정도냐면, 모바일 LTE 환경에서 첫 로딩 때 0.5~1초쯤 더 기다리게 되는 양이지요. 첫 페인트가 중요한 맥락이라면 아직 JS 쪽이 유리해 보입니다.
2. 브라우저 호환성
WasmGC 지원이 주요 브라우저에 다 깔렸다고 하는데, 막상 Safari 18 미만 환경에선 못 돌아갑니다. User-Agent 분기로 JS fallback 번들을 따로 떨어뜨려 둬야 했어요. 빌드 구성이 두 갈래로 갈리니까 CI 가 길어지는 건 덤이지요.
3. 디버깅
크롬 데브툴(Chrome DevTools) 의 .kt 소스맵이 아직 완전하지가 않습니다. 브레이크포인트가 엉뚱한 라인에 잡히거나, 콜스택이 변환 후 함수명으로 떨어지는 경우가 잦았어요. 결국 안드로이드 개발자가 가장 싫어하는 console.log 디버깅에 일부 의존하게 됐습니다. JVM 환경에선 상상도 못 할 일이었어요.

개인적으로는, 지금 프로덕션에 Wasm 타깃을 그대로 얹기는 쉽지 않아 보입니다. KMP Wasm 이 Beta, Component Model 지원이 EAP 단계라 두 축 모두 한 번씩 흔들릴 여지가 있어요. 사이드 프로젝트로 미리 손에 익혀두고, 본업 프로젝트는 Kotlin/JS 로 깔아두는 분리가 제 결론이었습니다.
6.8초가 다시 6.8초가 되기 전에
작년 가을, 이 사이드 프로젝트를 Kotlin/JS 로 처음 깔던 날 새벽 두 시까지 빌드 47초를 다섯 번 돌렸던 기억이 있어요. 한 줄 고치고 47초, 또 한 줄 고치고 47초. 디스코드 채널에 "Wasm 으로 갈아끼우면 좀 다를까" 하고 던졌던 질문이 지금 6.8초로 돌아온 셈이지요.

그날 새벽의 47초와 이번 주의 6.8초 사이, 제가 한 일이라곤 한 주에 한 번씩 같은 코드를 같은 노트북에서 돌려본 것뿐이었어요. 본업 빌드가 21초에서 6.8초로 줄어드는 그 다음 컷은 또 어느 새벽에 찾아오게 될까요. 같은 자리에 사이드 프로젝트 하나 깔아두신 분이라면, 이번 주에 한 번쯤 그 빌드 시간을 적어두실 자리이지 않나 싶네요.
'개발 일지' 카테고리의 다른 글
| 샤워하다 해법이 떠오른다면, 당신은 퇴근에 실패한 겁니다 (0) | 2026.07.11 |
|---|---|
| 주니어 멘토링 1년, 가르치다 시니어 개발자가 더 배운 5가지 (0) | 2026.07.10 |
| 안드로이드 17 정식 출시 D-1, 6년차가 베타 한 시즌을 돌아보며 (0) | 2026.06.15 |
| Solar Pro 3 vs Kanana-o vs HCX SEED Think — 한국어 5종 일감 비교 후기 (0) | 2026.06.13 |
| Koog 1.0 stable 출시 — Vadim Briliantov '안드 에이전트도 Kotlin으로', 본인 사이드 프로젝트에 첫 에이전트 끼운 한 주 일지 (0) | 2026.06.04 |