Aplikasi modern jarang berjalan di satu platform saja. Tim pengembang sering kali harus merilis produk untuk Android, iOS, dan web secara bersamaan, dengan logika bisnis yang identik—autentikasi, panggilan API, validasi input, caching. Menulis logika bisnis tiga kali (Kotlin, Swift, JavaScript) memboroskan waktu, membuka peluang inkonsistensi, dan memperlambat rilis fitur. Kotlin Multiplatform (KMP) menawarkan jalan tengah: tulis logika bisnis sekali dalam Kotlin, kompilasi ke target yang berbeda, sementara UI tetap ditulis dengan toolkit native masing-masing platform. Pada chapter ini kita akan memahami arsitektur KMP, membandingkannya dengan React Native dan Flutter, lalu menjalankan demo sederhana yang menggambarkan bagaimana satu kode bisnis berjalan di tiga platform berbeda.

Apa Itu KMP #

KMP adalah kemampuan kompilator Kotlin untuk menghasilkan artifact (bytecode JVM, JavaScript, native binary) dari kode yang sama. Kode yang berada di commonMain ditulis sekali; kode yang memerlukan API spesifik platform ditulis di source set terpisah (androidMain, iosMain, jvmMain) dan dihubungkan dengan mekanisme expect/actual yang akan dibahas di chapter tersendiri.

AspekKMPReact NativeFlutter
BahasaKotlinJavaScript/TypeScriptDart
UINative (SwiftUI, Compose)Native via bridgeCustom rendering engine
Logika bisnisKotlin (shared)JavaScript (shared)Dart (shared)
Komunikasi UI ↔ logikaDirect callJSON bridgeMethod channel
Performa UINativeBridge overheadCustom engine, dekat native

Tabel di atas menunjukkan tiga pendekatan berbeda untuk cross-platform development. KMP unggul karena UI tetap native—tidak ada bridge atau custom rendering engine yang mempengaruhi performa. React Native memakai bridge JavaScript yang dapat menjadi bottleneck pada interaksi intensif. Flutter menggambar sendiri seluruh UI-nya dengan engine Skia/Impeller, yang memberi konsistensi visual namun menambah ukuran aplikasi dan memerlukan adaptasi untuk perilaku native.

Logika Bisnis Bersama #

Kode yang umum dibagi meliputi: model data, validasi, panggilan API, manajemen state bisnis, dan kalkulasi. Kode ini ditulis dalam Kotlin murni tanpa memanggil API platform—hanya menggunakan kotlinstdlib dan library KMP seperti kotlinx.coroutines, kotlinx.serialization, atau ktor-client. Kode yang membutuhkan API platform (mis. membaca file, akses sensor, tampilkan toast) ditulis via interface yang disuntikkan ke logika bisnis.

kotlin
// pengenalan_kotlin_multiplatform.kt
// KMP overview: share business logic across platforms. UI stays native.
// Comparison with React Native/Flutter.
// This demo simulates a KMP project: shared Kotlin core + platform-specific implementations via interface.

// --- Shared business logic (would live in commonMain) ---
interface PlatformInfo {
    val name: String
    val version: String
    fun readLog(): String
}

data class Transaksi(val id: String, val jumlah: Long, val mataUang: String) {
    fun ringkas(): String = "Transaksi $id: $mataUang $jumlah"
}

// Pure Kotlin domain logic — works on every platform without changes
class LogikaBisnis(private val platform: PlatformInfo) {
    private val transaksi = mutableListOf<Transaksi>()

    fun catat(t: Transaksi) {
        require(t.jumlah > 0) { "jumlah harus positif" }
        transaksi.add(t)
    }

    fun total(): Long = transaksi.sumOf { it.jumlah }

    fun laporan(): String {
        val header = "Platform: ${platform.name} ${platform.version}"
        val body = transaksi.joinToString("\n") { "  - ${it.ringkas()}" }
        val total = "Total: ${transaksi.size} transaksi, ${total()} satuan"
        return "$header\n$body\n$total"
    }
}

// --- Platform-specific implementations (would live in platform source sets) ---
class PlatformAndroid : PlatformInfo {
    override val name = "Android"
    override val version = "14 (API 34)"
    override fun readLog() = "Log via android.util.Log"
}

class PlatformIos : PlatformInfo {
    override val name = "iOS"
    override val version = "17.2"
    override fun readLog() = "Log via os_log"
}

class PlatformJvm : PlatformInfo {
    override val name = "JVM"
    override val version = "OpenJDK 21"
    override fun readLog() = "Log via java.util.logging"
}

fun main() {
    // Simulasi: jalankan logika bisnis yang sama di tiga platform berbeda
    val targetPlatform = listOf(PlatformAndroid(), PlatformIos(), PlatformJvm())

    for (platform in targetPlatform) {
        println("=== Menjalankan logika bisnis di ${platform.name} ===")
        val logika = LogikaBisnis(platform)
        logika.catat(Transaksi("TRX-001", 50_000, "IDR"))
        logika.catat(Transaksi("TRX-002", 1_200, "USD"))
        println(logika.laporan())
        println("Logging: ${platform.readLog()}")
        println()
    }
}

Output yang Dihasilkan:

text
=== Menjalankan logika bisnis di Android ===
Platform: Android 14 (API 34)
  - Transaksi TRX-001: IDR 50000
  - Transaksi TRX-002: USD 1200
Total: 2 transaksi, 51200 satuan
Logging: Log via android.util.Log

=== Menjalankan logika bisnis di iOS ===
Platform: iOS 17.2
  - Transaksi TRX-001: IDR 50000
  - Transaksi TRX-002: USD 1200
Total: 2 transaksi, 51200 satuan
Logging: Log via os_log

=== Menjalankan logika bisnis di JVM ===
Platform: JVM OpenJDK 21
  - Transaksi TRX-001: IDR 50000
  - Transaksi TRX-002: USD 1200
Total: 2 transaksi, 51200 satuan
Logging: Log via java.util.logging

Mari kita bedah bagian kunci dari kode di atas:

  1. interface PlatformInfo: abstraksi yang berada di commonMain. Logika bisnis LogikaBisnis menerima instance PlatformInfo tanpa peduli platform mana yang aktif. Inilah inti KMP: kode bisnis tidak tahu platform—hanya tahu interface.
  2. data class Transaksi: model data murni Kotlin, tidak memanggil API platform. Dapat dipakai di Android, iOS, JVM, dan JS tanpa modifikasi. ringkas() memakai string template Kotlin yang berjalan di semua target.
  3. LogikaBisnis: class yang berisi aturan bisnis—require untuk validasi, akumulasi transaksi, perhitungan total. Seluruh kode ini berada di commonMain dan tidak peduli apakah dijalankan di Android atau iOS.
  4. PlatformAndroid, PlatformIos, PlatformJvm: tiga implementasi interface PlatformInfo. Pada proyek KMP nyata, ketiganya berada di source set terpisah (androidMain, iosMain, jvmMain) dan dihubungkan ke commonMain via expect/actual.
  5. Output menunjukkan tiga run: kode bisnis yang sama (LogikaBisnis) dipakai di tiga platform berbeda—hasil laporan identik, hanya header platform yang berbeda. Inilah bukti bahwa logika bisnis benar-benar terbagi.

UI Native Tetap Dipertahankan #

Berbeda dengan Flutter atau React Native yang memaksa satu toolkit UI, KMP membiarkan tim memilih toolkit terbaik untuk setiap platform. Di Android, gunakan Jetpack Compose; di iOS, gunakan SwiftUI. Logika bisnis KMP dipanggil dari UI melalui binding yang ringan, tanpa bridge JavaScript atau method channel.

kotlin Ilustrasi: panggilan dari Compose (Android)
// import androidx.compose.runtime.*
// import androidx.compose.material3.*
//
// @Composable
// fun TransaksiScreen(logika: LogikaBisnis) {
//     var laporan by remember { mutableStateOf(logika.laporan()) }
//     Column {
//         Text("Daftar Transaksi")
//         Text(laporan)
//         Button(onClick = { laporan = logika.laporan() }) {
//             Text("Refresh")
//         }
//     }
// }

Kode di atas tidak dijalankan dalam demo karena memerlukan library Compose. Yang penting: LogikaBisnis tidak peduli bahwa ia dipanggil dari Composable—pemanggilan adalah function call biasa, bukan RPC.

Kapan Tidak Memakai KMP #

KMP bukan solusi universal. Beberapa kasus di mana pendekatan lain lebih cocok:

  • Aplikasi yang 90% adalah UI dengan logika bisnis minimal—keuntungan berbagi kode kecil.
  • Tim sudah memiliki codebase React Native/Flutter yang matang—migrasi ke KMP mahal.
  • Tim tidak memiliki pengembang Kotlin—pembelajaran bahasa memerlukan investasi awal.
  • Aplikasi yang memerlukan UI pixel-perfect identik lintas platform—KMP tidak menyediakan ini karena UI native berbeda.

Ekosistem dan Maturitas #

Sejak 2023, KMP mencapai status stabil untuk banyak use case. Google mendukung KMP sebagai jalur resmi untuk berbagi kode antara Android dan iOS. Library populer seperti kotlinx.coroutines, kotlinx.serialization, ktor-client, SQLDelight, dan Koin telah mendukung multiplatform sejak lama. JetBrains juga merilis Compose Multiplatform yang memungkinkan UI Compose berjalan di iOS, Desktop, dan Web—pilihan alternatif untuk tim yang ingin berbagi UI juga.

Referensi Lanjutan #

  • Kotlin Multiplatform — halaman utama dokumentasi Kotlin Multiplatform untuk pengenalan arsitektur dan use case
  • JetBrains KMP docs — panduan JetBrains untuk pengembangan aplikasi Kotlin Multiplatform

Penutup #

KMP menawarkan keseimbangan antara berbagi kode dan menjaga UI native. Logika bisnis ditulis sekali dalam Kotlin; UI tetap memakai toolkit terbaik per platform. Chapter berikutnya akan masuk ke struktur proyek KMP yang konkret: bagaimana build.gradle.kts mendeklarasikan target, dan bagaimana source set commonMain, jvmMain, dan iosMain saling terkait.