Banyak proyek modern menargetkan lebih dari satu platform: Android dan iOS, server dan web, desktop dan mobile. Menulis logika bisnis dua kali untuk setiap platform memboroskan waktu dan menimbulkan ketidaksesuaian. Kotlin Multiplatform (KMP) hadir untuk menjawab masalah ini dengan pendekatan berbagi kode selektif. Pada chapter ini kita akan memahami konsep KMP, struktur source set, mekanisme expect/actual, dan use case utamanya.
Apa itu KMP #
Kotlin Multiplatform adalah kemampuan kompilator Kotlin untuk menargetkan beberapa platform sekaligus dari satu proyek Gradle yang sama. Kita menulis logika umum sekali, lalu menyediakan implementasi spesifik per platform hanya untuk bagian yang berbeda — misalnya akses basis data, jaringan, atau UI.
KMP tidak menggantikan UI native. Pendekatannya jelas berbeda dari framework cross-platform seperti Flutter atau React Native: KMP berbagi logika bisnis, sementara UI tetap ditulis dengan toolkit native (Jetpack Compose di Android, SwiftUI di iOS, Compose Multiplatform untuk lintas platform).
Struktur Source Set #
Proyek KMP mengatur kode dalam source set. Dua source set utama:
commonMain: kode yang berlaku untuk semua target. Hanya boleh memakai API Kotlin stdlib yang lintas platform dan library KMP.<platform>Main(mis.jvmMain,androidMain,iosMain,jsMain): kode khusus untuk satu target. Boleh memakai API spesifik platform (mis.java.util.*dijvmMain,FoundationdiiosMain).
Struktur folder tipikal terlihat seperti berikut:
proyek-kmp/
├── shared/
│ └── src/
│ ├── commonMain/
│ │ └── kotlin/com/example/Repository.kt
│ ├── androidMain/
│ │ └── kotlin/com/example/Platform.kt
│ ├── iosMain/
│ │ └── kotlin/com/example/Platform.kt
│ └── jvmMain/
│ └── kotlin/com/example/Platform.kt
└── build.gradle.ktsMekanisme expect/actual #
Jika commonMain butuh akses ke fitur yang implementasinya berbeda per platform (mis. membaca file, mendapatkan waktu sistem, atau UUID), kita pakai mekanisme expect/actual:
expect class PlatformInfo() {
val nama: String
fun detail(): String
}actual class PlatformInfo {
actual val nama = "Android"
actual fun detail() = "Berjalan di Android ${android.os.Build.VERSION.RELEASE}"
}Kompilator memverifikasi bahwa setiap expect di commonMain punya pasangan actual di setiap target. Jika ada target yang belum diisi, build gagal dengan pesan yang jelas.
Use Cases #
KMP paling sering dipakai untuk berbagi jenis kode berikut:
- Logika bisnis: aturan domain, validasi, perhitungan
- Akses data: repository, DAO, mappers
- Networking: HTTP client (Ktor), serialization, API contract
- Model data: data class, sealed class, enum yang dipakai lintas platform
- Logging dan utilitas: helper yang tidak bergantung UI
KMP vs Full Cross-Platform Framework #
Berikut perbandingan pendekatan KMP dengan framework cross-platform penuh:
| Aspek | Kotlin Multiplatform | Flutter / React Native |
|---|---|---|
| Apa yang dibagi | Logika bisnis | Logika + UI |
| UI native | Ya, full native | Tidak, render sendiri |
| Performa UI | Setara aplikasi native | Setara, tapi tidak 100% native |
| Adopsi bertahap | Bisa, satu modul kapan saja | Harus pilih di awal proyek |
| Ekosistem library | Library KMP + library native | Plugin framework sendiri |
Mendemonstrasikan Konsep Source Set #
Karena KMP memerlukan konfigurasi Gradle khusus, kita tidak bisa menjalankan modul commonMain secara langsung dengan kotlinc. Tetapi kita bisa menyimulasikan konsepnya dalam satu file Kotlin/JVM biasa lewat interface dan implementasi:
interface PlatformInfo {
val nama: String
fun detail(): String
}
class JvmPlatform : PlatformInfo {
override val nama = "JVM"
override fun detail() = "Bytecode berjalan di atas Java Virtual Machine"
}
class NativePlatform : PlatformInfo {
override val nama = "Native"
override fun detail() = "Dikompilasi menjadi biner asli via LLVM"
}
class JsPlatform : PlatformInfo {
override val nama = "JS"
override fun detail() = "Dikompilasi menjadi JavaScript untuk browser/Node.js"
}
fun main() {
val target = listOf(JvmPlatform(), NativePlatform(), JsPlatform())
println("Konsep source set platform pada KMP:")
target.forEach { p ->
println(" - ${p.nama}: ${p.detail()}")
}
}Output yang Dihasilkan:
Konsep source set platform pada KMP:
- JVM: Bytecode berjalan di atas Java Virtual Machine
- Native: Dikompilasi menjadi biner asli via LLVM
- JS: Dikompilasi menjadi JavaScript untuk browser/Node.jsMari kita bedah bagian pentingnya:
interface PlatformInfo: kontrak umum yang setara dengan deklarasiexpectdicommonMain.class JvmPlatform : PlatformInfo: implementasi konkret yang setara denganactualdijvmMain. ClassNativePlatformdanJsPlatformberperan sebagaiactualdi target lainnya.val target = listOf(JvmPlatform(), ...): semua implementasi disatukan dalam satu list bertipePlatformInfo, persis seperti saat kodecommonMainmemakai tipeexpectdan runtime menyelesaikan keactualyang sesuai.forEach { p -> ... }: pemanggilan method interface bersifat polimorfik — runtime memilih implementasi yang benar untuk setiap instance.
Referensi #
Referensi Lanjutan #
- Kotlin Multiplatform — halaman utama dokumentasi Kotlin Multiplatform untuk berbagi kode lintas target
- Kotlin Multiplatform Mobile getting started — panduan resmi memulai proyek KMP untuk Android dan iOS
Selanjutnya #
Kita sudah memahami struktur internal KMP dan target kompilasi. Pertanyaan terakhir di section ini: di mana Kotlin benar-benar dipakai di dunia nyata, dan oleh siapa? Chapter Use Case Kotlin akan menjawab dengan memetakan tujuh bidang utama pemakaian Kotlin, lengkap dengan contoh perusahaan yang sudah mengadopsinya.