Memilih framework backend adalah keputusan jangka panjang. Framework yang dipilih akan menentukan struktur proyek, pola penanganan error, cara pengujian, hingga strategi deployment. Kotlin punya dua framework utama dengan filosofi berbeda: Ktor yang ringan dan coroutine-native, serta Spring Boot yang matang dengan ekosistem luas. Pada chapter ini kita akan membandingkan keduanya melalui kriteria konkret dan menjalankan program kecil yang merekomendasikan pilihan berdasarkan parameter tim.

Ktor vs Spring Boot #

Ktor dikembangkan oleh JetBrains dan dirancang sejak awal sebagai framework coroutine-native. Ktor memakai DSL Kotlin untuk routing dan konfigurasi plugin, sehingga kode backend terlihat seperti kode Kotlin biasa — tanpa anotasi yang berlebihan. Spring Boot dibangun di atas Spring Framework yang sudah matang, memakai anotasi @RestController, @Service, @Repository sebagai mekanisme utama.

Perbedaan filosofi ini memengaruhi banyak aspek praktis. Boot time Ktor sering di bawah satu detik karena tidak ada scan anotasi. Boot time Spring Boot dapat beberapa detik karena container IoC memindai seluruh classpath. Untuk microservice dengan ratusan instance, selisih ini berarti penghematan biaya server nyata.

Kriteria Keputusan #

KriteriaKtor unggulSpring Boot unggul
Ukuran tim kecil (<=3)Ya—
Butuh ekosistem matang—Ya
Preferensi sintaks ringkasYa—
Latensi target < 50msYa—
Banyak integration library siap—Ya
Coroutines sebagai warga kelas satuYaSebagian

Model Keputusan Sederhana #

Agar perbandingan lebih konkret, kita akan menulis program yang menerima kriteria tim dan menghasilkan rekomendasi framework. Program ini juga mencetak tabel trade-off antar aspek.

kotlin
// memilih_backend_framework.kt
// Membandingkan Ktor dan Spring Boot lewat model sederhana:
// memilih framework berdasarkan kriteria tim, lalu memetakan trade-off.

data class KriteriaBackend(
    val ukuranTim: Int,
    val butuhEcosystemMatang: Boolean,
    val preferConcise: Boolean,
    val targetLatencyMs: Int
)

data class SkorFramework(val nama: String, val ktor: Int, val spring: Int)

// Fungsi rekomendasi memetakan kriteria ke pilihan framework
fun rekomendasi(k: KriteriaBackend): String {
    val skorKtor = when {
        k.ukuranTim <= 3 -> 3
        k.preferConcise -> 2
        k.targetLatencyMs < 50 -> 2
        else -> 0
    }
    val skorSpring = when {
        k.ukuranTim > 5 -> 3
        k.butuhEcosystemMatang -> 2
        k.targetLatencyMs >= 50 -> 1
        else -> 0
    }
    return when {
        skorKtor > skorSpring -> "Ktor"
        skorSpring > skorKtor -> "Spring Boot"
        else -> "Keduanya seimbang"
    }
}

fun main() {
    println("=== Perbandingan Ktor vs Spring Boot ===")
    val kriteria = listOf(
        KriteriaBackend(ukuranTim = 2, butuhEcosystemMatang = false, preferConcise = true, targetLatencyMs = 30),
        KriteriaBackend(ukuranTim = 12, butuhEcosystemMatang = true, preferConcise = false, targetLatencyMs = 100),
        KriteriaBackend(ukuranTim = 5, butuhEcosystemMatang = true, preferConcise = true, targetLatencyMs = 50)
    )
    kriteria.forEachIndexed { i, k ->
        println("Tim #${i + 1}: $k -> rekomendasi: ${rekomendasi(k)}")
    }

    println("\n=== Tabel trade-off ===")
    val tradeoff = listOf(
        SkorFramework("Boot time (cold start)", ktor = 9, spring = 5),
        SkorFramework("Ekosistem library", ktor = 6, spring = 10),
        SkorFramework("Coroutines native", ktor = 10, spring = 7),
        SkorFramework("Learning curve", ktor = 8, spring = 5),
        SkorFramework("Konfigurasi XML/annotasi", ktor = 4, spring = 9)
    )
    println("%-30s | %s | %s".format("Aspek", "Ktor", "Spring"))
    println("-".repeat(50))
    tradeoff.forEach {
        println("%-30s | %4d  | %4d".format(it.nama, it.ktor, it.spring))
    }
}

Output yang Dihasilkan:

text
=== Perbandingan Ktor vs Spring Boot ===
Tim #1: KriteriaBackend(ukuranTim=2, butuhEcosystemMatang=false, preferConcise=true, targetLatencyMs=30) -> rekomendasi: Ktor
Tim #2: KriteriaBackend(ukuranTim=12, butuhEcosystemMatang=true, preferConcise=false, targetLatencyMs=100) -> rekomendasi: Spring Boot
Tim #3: KriteriaBackend(ukuranTim=5, butuhEcosystemMatang=true, preferConcise=true, targetLatencyMs=50) -> rekomendasi: Keduanya seimbang

=== Tabel trade-off ===
Aspek                          | Ktor | Spring
--------------------------------------------------
Boot time (cold start)         |    9  |    5
Ekosistem library              |    6  |   10
Coroutines native              |   10  |    7
Learning curve                 |    8  |    5
Konfigurasi XML/annotasi       |    4  |    9

Mari kita bedah bagian penting kode di atas:

  1. data class KriteriaBackend: model input dengan empat atribut. Semua field val (immutable) karena kriteria tidak berubah setelah dibuat.
  2. fun rekomendasi(k: KriteriaBackend): String: menghitung skor Ktor dan Spring berdasarkan aturan when. Cabang else -> 0 memastikan skor fallback eksplisit.
  3. when { skorKtor > skorSpring -> ... }: pemilihan hasil dengan comparison eksplisit, menghindari kebergantungan pada asumsi jika kedua skor seri.
  4. "%-30s | %4d | %4d".format(...): format string ala C untuk menyusun tabel rapi. Lebar kolom tetap menjaga output konsisten walau teks bervariasi.

Trade-off Praktis #

Skor pada tabel trade-off bersifat relatif, bukan absolut. Ktor mendapat skor 9 untuk boot time karena startup-nya cepat dan tidak ada scan anotasi. Spring Boot mendapat skor 10 untuk ekosistem karena ribuan starter library siap pakai — dari Spring Data JPA hingga Spring Security. Skor learning curve lebih tinggi untuk Ktor karena konsep plugin dan DSL mudah dipahami jika pembaca sudah familiar Kotlin.

Kapan Memilih Ktor #

Ktor cocok untuk microservice dengan jejak memori kecil, layanan edge yang butuh latensi rendah, atau proyek startup yang ingin iterasi cepat. Tim kecil dengan dua sampai lima developer biasanya menemukan DSL Ktor lebih ringkas daripada anotasi Spring. Plugin Ktor juga komposabel — kita hanya memasang yang dibutuhkan, tanpa overhead fitur yang tidak terpakai.

Kapan Memilih Spring Boot #

Spring Boot unggul untuk aplikasi enterprise dengan banyak integration: JPA, Security, Batch, Cloud. Ekosistem starter library yang luas berarti banyak masalah sudah punya solusi siap. Tim besar yang sudah mahir Spring akan produktif lebih cepat karena konsep IoC, anotasi, dan konfigurasi sudah familiar.

Referensi Lanjutan #

Selanjutnya #

Setelah memilih framework, langkah berikutnya adalah memahami fondasi Ktor. Chapter Ktor Fundamentals akan membahas Application class, pipeline phases, dan plugin — tiga konsep inti yang akan dipakai sepanjang section Ktor ini.