Home > Blog > tech

Kotlin Multiplatform (KMP) คืออะไร? สอนสร้าง Cross-Platform App ด้วย Kotlin 2026

kotlin multiplatform kmp guide
Kotlin Multiplatform KMP Guide 2026
2026-04-10 | tech | 3500 words

ในปี 2026 การพัฒนา App สำหรับหลาย Platform พร้อมกันกลายเป็นความจำเป็น ลูกค้าต้องการ App ทั้ง Android, iOS, Web และ Desktop แต่การเขียน Code แยกทุก Platform เป็นเรื่องที่สิ้นเปลืองทรัพยากรมหาศาล Kotlin Multiplatform (KMP) คือทางออกที่ JetBrains นำเสนอ โดยให้นักพัฒนาสามารถ Share Business Logic ข้ามทุก Platform ได้อย่างแท้จริง โดยไม่ต้องเสียสละ Native Performance หรือ Native UI ของแต่ละ Platform

บทความนี้จะพาคุณเรียนรู้ Kotlin Multiplatform ตั้งแต่แนวคิดพื้นฐาน ไปจนถึงการสร้างโปรเจกต์จริง พร้อมเปรียบเทียบกับ Flutter และ React Native อย่างละเอียด เหมาะสำหรับทั้งนักพัฒนา Android ที่อยากขยาย Skill และนักพัฒนาที่กำลังมองหา Cross-Platform Solution ที่ดีที่สุดในปี 2026

Kotlin Multiplatform (KMP) คืออะไร?

Kotlin Multiplatform (KMP) คือเทคโนโลยีจาก JetBrains ที่อนุญาตให้คุณเขียน Business Logic เพียงครั้งเดียวด้วยภาษา Kotlin แล้วนำไปใช้ร่วมกันบน Android, iOS, Web, Desktop และ Server ได้ทันที สิ่งที่ทำให้ KMP แตกต่างจาก Cross-Platform Framework อื่นๆ คือมันไม่ได้พยายาม Abstract ทุกอย่างออกจาก Platform แต่ให้คุณ Share เฉพาะส่วนที่ควร Share (เช่น Networking, Data Layer, Business Logic) และเขียน UI แบบ Native ตามแต่ละ Platform ได้

JetBrains ประกาศให้ KMP เป็น Stable ตั้งแต่ Kotlin 1.9.20 และในปี 2026 ด้วย Kotlin 2.1+ KMP ได้รับการพัฒนาจนมีความสมบูรณ์สูงมาก Google เองก็ประกาศ Official Support สำหรับ KMP ใน Android Development ทำให้ KMP ได้รับความเชื่อมั่นจากชุมชนนักพัฒนาทั่วโลก

หลักการทำงานของ KMP

KMP ใช้ Kotlin Compiler ที่สามารถ Compile Code ไปเป็น Target ต่างๆ ได้:

KMP vs Flutter vs React Native — เปรียบเทียบ Cross-Platform 2026

ก่อนที่จะลงลึกใน KMP เรามาเปรียบเทียบกับ Flutter และ React Native ซึ่งเป็น Cross-Platform Framework ยอดนิยมอีกสองตัว

FeatureKMPFlutterReact Native
ภาษาKotlinDartJavaScript/TypeScript
UI ApproachNative UI / Compose MultiplatformCustom Rendering EngineBridge to Native UI
Code SharingBusiness Logic + optional UIทุกอย่างรวม UIส่วนใหญ่รวม UI
PerformanceNative-levelNear-nativeGood (New Architecture)
iOS Integrationดีมาก (Swift interop)ปานกลางดี (Native Modules)
Learning Curveง่ายสำหรับ Android Devต้องเรียน Dartง่ายสำหรับ Web Dev
Web SupportKotlin/JS, Kotlin/WasmFlutter WebReact Native Web
Desktop SupportCompose MultiplatformFlutter Desktopจำกัด
Backed byJetBrains + GoogleGoogleMeta
Maturity (2026)Stable, เติบโตเร็วMatureMature
เลือกเมื่อไหร่? ถ้าทีมคุณเป็น Android/Kotlin Developer อยู่แล้ว → KMP เป็นทางเลือกที่ดีที่สุด ถ้าทีมเป็น Web Developer → React Native ถ้าต้องการ Pixel-perfect UI ทุก Platform → Flutter ถ้าต้องการ Best Native Integration → KMP

Kotlin Basics สำหรับคนที่ยังไม่รู้จัก Kotlin

ก่อนจะเริ่ม KMP มาทบทวน Kotlin Syntax พื้นฐานกันก่อน Kotlin เป็นภาษาที่สั้นกระชับ Type-safe และ Null-safe ออกแบบโดย JetBrains เป็นภาษาที่ Java Developer จะคุ้นเคยทันที

// Variables
val name: String = "KMP"        // Immutable (val = final)
var count: Int = 0              // Mutable

// Null Safety - จุดเด่นของ Kotlin
val nullableName: String? = null
val length = nullableName?.length ?: 0  // Elvis operator

// Data Classes
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Functions
fun greet(name: String): String = "Hello, $name!"

// Extension Functions
fun String.addExclamation(): String = "$this!"

// Higher-order Functions
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
val evens = numbers.filter { it % 2 == 0 }

// Coroutines (async/await)
suspend fun fetchUser(id: Int): User {
    return apiService.getUser(id)  // suspend function
}

// Sealed Classes
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

โครงสร้าง KMP Project

KMP Project มีโครงสร้างหลักแบ่งเป็น 3 ส่วน: Shared Module (Business Logic ที่ใช้ร่วมกัน), Android App และ iOS App

my-kmp-project/
├── shared/                    # Shared Kotlin Code
│   ├── src/
│   │   ├── commonMain/       # Code ที่ใช้ทุก Platform
│   │   │   └── kotlin/
│   │   │       ├── data/
│   │   │       │   ├── repository/
│   │   │       │   └── model/
│   │   │       ├── domain/
│   │   │       │   └── usecase/
│   │   │       ├── network/
│   │   │       │   └── ApiService.kt
│   │   │       └── Platform.kt
│   │   ├── commonTest/       # Shared Tests
│   │   ├── androidMain/      # Android-specific code
│   │   │   └── kotlin/
│   │   │       └── Platform.android.kt
│   │   ├── iosMain/          # iOS-specific code
│   │   │   └── kotlin/
│   │   │       └── Platform.ios.kt
│   │   ├── jsMain/           # Web-specific code
│   │   └── desktopMain/      # Desktop-specific code
│   └── build.gradle.kts
├── androidApp/               # Android Application
│   ├── src/main/
│   │   ├── java/
│   │   └── res/
│   └── build.gradle.kts
├── iosApp/                   # iOS Application (Xcode Project)
│   ├── iosApp/
│   │   ├── ContentView.swift
│   │   └── iOSApp.swift
│   └── iosApp.xcodeproj
├── build.gradle.kts          # Root build file
└── settings.gradle.kts

ตั้งค่า build.gradle.kts สำหรับ Shared Module

// shared/build.gradle.kts
plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    alias(libs.plugins.kotlinSerialization)
}

kotlin {
    // Android Target
    androidTarget {
        compilations.all {
            compileTaskProvider.configure {
                compilerOptions {
                    jvmTarget.set(JvmTarget.JVM_17)
                }
            }
        }
    }

    // iOS Targets
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "Shared"
            isStatic = true
        }
    }

    // Desktop Target
    jvm("desktop")

    // Web Target
    js(IR) {
        browser()
    }

    sourceSets {
        commonMain.dependencies {
            implementation(libs.ktor.client.core)
            implementation(libs.ktor.client.content.negotiation)
            implementation(libs.ktor.serialization.kotlinx.json)
            implementation(libs.kotlinx.coroutines.core)
            implementation(libs.kotlinx.serialization.json)
            implementation(libs.sqldelight.runtime)
            implementation(libs.koin.core)
        }

        androidMain.dependencies {
            implementation(libs.ktor.client.android)
            implementation(libs.sqldelight.android.driver)
            implementation(libs.koin.android)
        }

        iosMain.dependencies {
            implementation(libs.ktor.client.darwin)
            implementation(libs.sqldelight.native.driver)
        }

        commonTest.dependencies {
            implementation(libs.kotlin.test)
            implementation(libs.kotlinx.coroutines.test)
        }
    }
}

expect/actual — หัวใจของ KMP

กลไก expect/actual คือวิธีที่ KMP จัดการกับ Platform-specific Code คุณประกาศ expect ใน Common Code เพื่อบอกว่า "ฉันต้องการสิ่งนี้" แล้วแต่ละ Platform จะ Implement actual ตามความเหมาะสม

// commonMain/kotlin/Platform.kt
expect class Platform() {
    val name: String
    val version: String
}

expect fun getPlatformName(): String

// androidMain/kotlin/Platform.android.kt
actual class Platform actual constructor() {
    actual val name: String = "Android"
    actual val version: String = "${android.os.Build.VERSION.SDK_INT}"
}

actual fun getPlatformName(): String = "Android ${android.os.Build.VERSION.SDK_INT}"

// iosMain/kotlin/Platform.ios.kt
import platform.UIKit.UIDevice

actual class Platform actual constructor() {
    actual val name: String = "iOS"
    actual val version: String = UIDevice.currentDevice.systemVersion
}

actual fun getPlatformName(): String = "iOS ${UIDevice.currentDevice.systemVersion}"

// desktopMain/kotlin/Platform.desktop.kt
actual class Platform actual constructor() {
    actual val name: String = "Desktop"
    actual val version: String = System.getProperty("os.version") ?: "Unknown"
}

actual fun getPlatformName(): String = "Desktop JVM"
กฎ expect/actual: ทุก expect declaration ต้องมี actual implementation ใน ทุก target platform ที่กำหนดไว้ ถ้า Target มี Android + iOS + Desktop ต้องมี actual ทั้ง 3 ที่ ไม่งั้น Compile ไม่ผ่าน

KMP สำหรับ Mobile — Compose Multiplatform

Compose Multiplatform คือ Declarative UI Framework จาก JetBrains ที่ทำให้ Jetpack Compose (Android) สามารถทำงานได้บน iOS, Desktop และ Web ได้ด้วย ทำให้คุณสามารถ Share ทั้ง Business Logic และ UI Code ข้าม Platform ได้เหมือน Flutter แต่ด้วย Kotlin

// Shared Compose UI - ใช้ได้ทุก Platform
@Composable
fun UserListScreen(viewModel: UserViewModel) {
    val users by viewModel.users.collectAsState()
    val isLoading by viewModel.isLoading.collectAsState()

    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp)
    ) {
        Text(
            text = "Users",
            style = MaterialTheme.typography.headlineMedium,
            modifier = Modifier.padding(bottom = 16.dp)
        )

        if (isLoading) {
            CircularProgressIndicator(
                modifier = Modifier.align(Alignment.CenterHorizontally)
            )
        }

        LazyColumn {
            items(users) { user ->
                UserCard(user = user)
            }
        }
    }
}

@Composable
fun UserCard(user: User) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 4.dp),
        elevation = CardDefaults.cardElevation(2.dp)
    ) {
        Row(
            modifier = Modifier.padding(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            AsyncImage(
                model = user.avatarUrl,
                contentDescription = user.name,
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Column {
                Text(user.name, style = MaterialTheme.typography.bodyLarge)
                Text(user.email, style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}

Compose Multiplatform บน iOS

บน iOS Compose Multiplatform จะ Render ผ่าน Skia Engine (เหมือน Flutter) ซึ่งให้ Pixel-perfect UI ข้าม Platform แต่คุณก็สามารถผสม Native SwiftUI Component ได้ตามต้องการ

// iOS Entry Point - iosApp/ContentView.swift
import SwiftUI
import Shared

struct ComposeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        MainViewControllerKt.MainViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController,
                                context: Context) {}
}

struct ContentView: View {
    var body: some View {
        ComposeView()
            .ignoresSafeArea(.keyboard)
    }
}

KMP + SwiftUI สำหรับ iOS

ถ้าคุณต้องการ Native Look & Feel สูงสุดบน iOS คุณสามารถเลือกใช้ SwiftUI สำหรับ UI Layer และใช้ KMP Shared Module เฉพาะ Business Logic ได้ วิธีนี้เป็นที่นิยมมากเพราะ iOS Developer ยังคงเขียน UI ด้วยเครื่องมือที่คุ้นเคย

// iosApp/UserListView.swift
import SwiftUI
import Shared  // KMP Shared Framework

struct UserListView: View {
    @StateObject private var viewModel = IOSUserViewModel()

    var body: some View {
        NavigationStack {
            List(viewModel.users, id: \.id) { user in
                HStack {
                    AsyncImage(url: URL(string: user.avatarUrl))
                        .frame(width: 44, height: 44)
                        .clipShape(Circle())
                    VStack(alignment: .leading) {
                        Text(user.name).font(.headline)
                        Text(user.email).font(.caption).foregroundStyle(.secondary)
                    }
                }
            }
            .navigationTitle("Users")
            .task { await viewModel.loadUsers() }
        }
    }
}

// Bridge KMP ViewModel to SwiftUI
class IOSUserViewModel: ObservableObject {
    @Published var users: [User] = []
    private let repository = UserRepository()  // KMP Shared Class

    func loadUsers() async {
        do {
            let result = try await repository.getUsers()
            DispatchQueue.main.async {
                self.users = result
            }
        } catch {
            print("Error: \(error)")
        }
    }
}

KMP สำหรับ Web — Kotlin/JS และ Kotlin/Wasm

KMP ไม่ได้จำกัดเฉพาะ Mobile เท่านั้น คุณสามารถนำ Shared Code ไปใช้บน Web ได้ผ่าน Kotlin/JS (Compile เป็น JavaScript) หรือ Kotlin/Wasm (Compile เป็น WebAssembly) ซึ่งทั้งสองวิธีมีข้อดีแตกต่างกัน

// Kotlin/JS — ใช้ Shared Code ใน Web App
// build.gradle.kts
kotlin {
    js(IR) {
        browser {
            commonWebpackConfig {
                cssSupport { enabled.set(true) }
            }
        }
        binaries.executable()
    }
}

// jsMain/kotlin/Main.kt
import kotlinx.browser.document
import kotlinx.browser.window

fun main() {
    val repository = UserRepository()  // KMP Shared Code!

    window.onload = {
        document.getElementById("app")?.innerHTML = renderApp()
    }
}

// Kotlin/Wasm — New in 2026, High Performance
kotlin {
    wasmJs {
        browser()
        binaries.executable()
    }
}

KMP สำหรับ Desktop

ด้วย Compose Multiplatform คุณสามารถสร้าง Desktop Application สำหรับ Windows, macOS และ Linux ได้อย่างง่ายดาย โดยใช้ Code Base เดียวกับ Mobile

// desktopMain/kotlin/Main.kt
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

fun main() = application {
    Window(
        onCloseRequest = ::exitApplication,
        title = "KMP Desktop App"
    ) {
        App()  // Same Composable as Mobile!
    }
}

// Shared App Composable
@Composable
fun App() {
    MaterialTheme {
        val viewModel = remember { UserViewModel() }
        UserListScreen(viewModel = viewModel)
    }
}

Ktor — Shared HTTP Client ข้ามทุก Platform

Ktor เป็น HTTP Client/Server Framework จาก JetBrains ที่ออกแบบมาเพื่อ KMP โดยเฉพาะ คุณเขียน Networking Code ครั้งเดียวแล้วใช้ได้ทุก Platform โดยแต่ละ Platform จะใช้ Engine ที่เหมาะสม (OkHttp บน Android, URLSession บน iOS เป็นต้น) คล้ายกับแนวคิด REST API Design ที่เราเคยพูดถึง

// commonMain/kotlin/network/ApiService.kt
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json

class ApiService {
    private val client = HttpClient {
        install(ContentNegotiation) {
            json(Json {
                ignoreUnknownKeys = true
                prettyPrint = true
                isLenient = true
            })
        }
    }

    suspend fun getUsers(): List<User> {
        return client.get("https://api.example.com/users").body()
    }

    suspend fun getUserById(id: Int): User {
        return client.get("https://api.example.com/users/$id").body()
    }

    suspend fun createUser(user: CreateUserRequest): User {
        return client.post("https://api.example.com/users") {
            contentType(ContentType.Application.Json)
            setBody(user)
        }.body()
    }
}

// Data Models — Shared across all platforms
@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String,
    val avatarUrl: String
)

@Serializable
data class CreateUserRequest(
    val name: String,
    val email: String
)

Platform-specific HTTP Engine

// androidMain — ใช้ OkHttp
actual fun createHttpClient(): HttpClient = HttpClient(OkHttp)

// iosMain — ใช้ Darwin (URLSession)
actual fun createHttpClient(): HttpClient = HttpClient(Darwin)

// desktopMain — ใช้ CIO
actual fun createHttpClient(): HttpClient = HttpClient(CIO)

SQLDelight — Shared Database ข้ามทุก Platform

SQLDelight จาก Square (ผู้สร้าง Cash App) เป็น Database Library ที่ออกแบบมาเพื่อ KMP ทำงานคล้ายกับ Room บน Android แต่ใช้ได้ทุก Platform คุณเขียน SQL Schema ครั้งเดียว แล้ว SQLDelight จะ Generate Type-safe Kotlin Code ให้อัตโนมัติ เปรียบเทียบได้กับ Prisma ORM ในโลก JavaScript

-- shared/src/commonMain/sqldelight/com/example/db/User.sq

-- สร้างตาราง
CREATE TABLE UserEntity (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    avatar_url TEXT NOT NULL DEFAULT '',
    created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Query
selectAll:
SELECT * FROM UserEntity ORDER BY created_at DESC;

selectById:
SELECT * FROM UserEntity WHERE id = :id;

insert:
INSERT INTO UserEntity(name, email, avatar_url)
VALUES (:name, :email, :avatarUrl);

deleteById:
DELETE FROM UserEntity WHERE id = :id;

searchByName:
SELECT * FROM UserEntity WHERE name LIKE '%' || :query || '%';
// ใช้งาน SQLDelight ใน Shared Code
class LocalDatabase(driverFactory: DatabaseDriverFactory) {
    private val database = AppDatabase(driverFactory.createDriver())
    private val queries = database.userEntityQueries

    fun getAllUsers(): List<UserEntity> {
        return queries.selectAll().executeAsList()
    }

    fun getUserById(id: Long): UserEntity? {
        return queries.selectById(id).executeAsOneOrNull()
    }

    fun insertUser(name: String, email: String, avatarUrl: String) {
        queries.insert(name, email, avatarUrl)
    }

    fun deleteUser(id: Long) {
        queries.deleteById(id)
    }
}

// expect/actual สำหรับ Database Driver
expect class DatabaseDriverFactory {
    fun createDriver(): SqlDriver
}

// androidMain
actual class DatabaseDriverFactory(private val context: Context) {
    actual fun createDriver(): SqlDriver {
        return AndroidSqliteDriver(AppDatabase.Schema, context, "app.db")
    }
}

// iosMain
actual class DatabaseDriverFactory {
    actual fun createDriver(): SqlDriver {
        return NativeSqliteDriver(AppDatabase.Schema, "app.db")
    }
}

Koin — Dependency Injection สำหรับ KMP

Koin เป็น Lightweight DI Framework ที่รองรับ KMP อย่างสมบูรณ์ ใช้ง่ายกว่า Dagger/Hilt มากเพราะไม่ต้อง Annotation Processing เหมาะสำหรับโปรเจกต์ KMP ที่ต้องจัดการ Dependency ข้ามหลาย Platform เป็นส่วนหนึ่งของ Design Patterns ที่ดีในการพัฒนา Software

// commonMain/kotlin/di/SharedModule.kt
import org.koin.dsl.module

val sharedModule = module {
    single { ApiService() }
    single { UserRepository(get(), get()) }
    factory { GetUsersUseCase(get()) }
}

// androidMain/kotlin/di/AndroidModule.kt
val androidModule = module {
    single { DatabaseDriverFactory(get()) }
    single { LocalDatabase(get()) }
}

// iosMain/kotlin/di/IosModule.kt
val iosModule = module {
    single { DatabaseDriverFactory() }
    single { LocalDatabase(get()) }
}

// KMP App Initialization
fun initKoin() {
    startKoin {
        modules(sharedModule, platformModule())
    }
}

// expect/actual for platform module
expect fun platformModule(): Module

Testing Shared Code ใน KMP

หนึ่งในข้อดีที่สำคัญที่สุดของ KMP คือคุณเขียน Test ครั้งเดียวสำหรับ Shared Code แล้ว Test นั้นจะทำงานบนทุก Platform ที่ Support ทำให้มั่นใจว่า Business Logic ทำงานถูกต้องบนทุก Platform โดยใช้แนวคิดจาก Software Testing ที่ดี

// commonTest/kotlin/UserRepositoryTest.kt
import kotlin.test.*
import kotlinx.coroutines.test.runTest

class UserRepositoryTest {
    private lateinit var repository: UserRepository
    private lateinit var fakeApi: FakeApiService
    private lateinit var fakeDb: FakeLocalDatabase

    @BeforeTest
    fun setup() {
        fakeApi = FakeApiService()
        fakeDb = FakeLocalDatabase()
        repository = UserRepository(fakeApi, fakeDb)
    }

    @Test
    fun `getUsers returns cached data when available`() = runTest {
        // Given
        fakeDb.insertUser("John", "john@test.com", "")

        // When
        val result = repository.getUsers(forceRefresh = false)

        // Then
        assertEquals(1, result.size)
        assertEquals("John", result.first().name)
    }

    @Test
    fun `getUsers fetches from API when cache is empty`() = runTest {
        // Given
        fakeApi.users = listOf(
            User(1, "Jane", "jane@test.com", "")
        )

        // When
        val result = repository.getUsers(forceRefresh = false)

        // Then
        assertEquals(1, result.size)
        assertEquals("Jane", result.first().name)
        assertTrue(fakeApi.fetchCalled)
    }

    @Test
    fun `getUsers forces API refresh when requested`() = runTest {
        // Given
        fakeDb.insertUser("Old", "old@test.com", "")
        fakeApi.users = listOf(User(1, "New", "new@test.com", ""))

        // When
        val result = repository.getUsers(forceRefresh = true)

        // Then
        assertTrue(fakeApi.fetchCalled)
        assertEquals("New", result.first().name)
    }
}

KMP ใน Production — บริษัทที่ใช้งานจริง

KMP ไม่ใช่แค่เทคโนโลยีทดลอง แต่ถูกใช้ใน Production โดยบริษัทระดับโลกหลายแห่ง:

บริษัทการใช้งาน KMPผลลัพธ์
NetflixProdicle App — Share Business Logic ระหว่าง Android/iOS สำหรับทีม Productionลดเวลาพัฒนา Feature ใหม่ 50%
Cash App (Square)ใช้ KMP Share Networking, Data Layer, Business Logic ระหว่าง Android/iOSCode Sharing 60%+ ลด Bug ข้าม Platform
PhilipsHealth App Share Medical Logic ข้ามทุก Platform ด้วย KMPลดทีม Dev ที่ต้องการ รับประกันความถูกต้องเท่ากันทุก Platform
VMwareWorkspace ONE SDK ใช้ KMP สำหรับ Share Code ข้าม Mobile PlatformMaintain SDK เดียวแทนที่จะเป็นสอง Codebase
TouchlabConsultancy ที่เชี่ยวชาญ KMP ช่วยหลายบริษัทย้ายมา KMPสร้าง SKIE Library ช่วย Swift Interop
ForbesForbes Mobile App ใช้ KMP Share Content Layerเร่ง Feature Parity ระหว่าง Android/iOS

KMP vs Compose Multiplatform — ต่างกันอย่างไร?

หลายคนสับสนระหว่าง KMP กับ Compose Multiplatform เพราะชื่อคล้ายกัน แต่จริงๆ แล้วต่างกันชัดเจน:

กล่าวง่ายๆ คือ KMP คือ Foundation และ Compose Multiplatform คือ UI Layer ที่เสริมด้านบน คุณสามารถใช้ KMP โดยไม่ใช้ Compose Multiplatform ได้ (เขียน Native UI แทน) แต่ไม่สามารถใช้ Compose Multiplatform โดยไม่มี KMP ได้

ข้อจำกัดและข้อควรพิจารณา

แม้ KMP จะมีข้อดีมากมาย แต่ก็ยังมีข้อจำกัดที่ควรรู้ก่อนตัดสินใจใช้งาน:

คำแนะนำ: เริ่มจาก Share เฉพาะ Networking + Data Layer ก่อน แล้วค่อยๆ ขยาย Shared Code เมื่อทีมคุ้นเคย อย่ารีบ Share UI ทั้งหมดตั้งแต่แรก

Migration จาก Native สู่ KMP — Step-by-Step

ถ้าคุณมี App Native อยู่แล้ว (Android + iOS แยกกัน) การ Migrate มา KMP ไม่จำเป็นต้องทำทีเดียว สามารถทำทีละส่วนได้:

Phase 1: เริ่มจาก Data Models

// ย้าย Data Models มา commonMain
@Serializable
data class Product(
    val id: String,
    val name: String,
    val price: Double,
    val category: String,
    val imageUrl: String
)

// ทั้ง Android และ iOS ใช้ Model เดียวกัน
// ลดโอกาสที่ Data จะไม่ตรงกัน

Phase 2: ย้าย Networking Layer

// ย้าย API Service มา commonMain
class ProductApi(private val client: HttpClient) {
    suspend fun getProducts(): List<Product> {
        return client.get("/api/products").body()
    }
}

// Android และ iOS เรียกใช้ ProductApi ตัวเดียวกัน

Phase 3: ย้าย Business Logic

// Repository Pattern ใน commonMain
class ProductRepository(
    private val api: ProductApi,
    private val db: LocalDatabase
) {
    suspend fun getProducts(forceRefresh: Boolean = false): List<Product> {
        if (!forceRefresh) {
            val cached = db.getProducts()
            if (cached.isNotEmpty()) return cached
        }
        val products = api.getProducts()
        db.saveProducts(products)
        return products
    }

    suspend fun searchProducts(query: String): List<Product> {
        return db.searchProducts(query)
    }
}

Phase 4: พิจารณา Shared UI (optional)

ขั้นตอนนี้เป็น Optional คุณสามารถเลือก Share UI ด้วย Compose Multiplatform หรือยังคงใช้ Native UI ก็ได้ การตัดสินใจขึ้นอยู่กับทีมและความต้องการของโปรเจกต์

KMP Ecosystem ที่ควรรู้จัก

Libraryหน้าที่Platform Support
KtorHTTP Client/ServerAll Platforms
SQLDelightType-safe SQL DatabaseAll Platforms
KoinDependency InjectionAll Platforms
Kotlinx.serializationJSON/CBOR SerializationAll Platforms
Kotlinx.coroutinesAsync/ConcurrencyAll Platforms
Kotlinx.datetimeDate/Time utilitiesAll Platforms
Compose MultiplatformDeclarative UIAndroid, iOS, Desktop, Web
Multiplatform SettingsSharedPreferences/UserDefaultsAll Platforms
SKIEBetter Swift InteropiOS
KMM-ViewModelShared ViewModelAndroid, iOS
NapierLoggingAll Platforms
KamelImage Loading for ComposeAll Compose Platforms

สร้างโปรเจกต์ KMP แรก — Quick Start

วิธีที่ง่ายที่สุดในการเริ่ม KMP คือใช้ KMP Wizard จาก JetBrains:

  1. ไปที่ kmp.jetbrains.com
  2. เลือก Platform ที่ต้องการ (Android + iOS + Desktop + Web)
  3. เลือก Libraries ที่ต้องการ (Ktor, SQLDelight, Koin)
  4. Generate Project แล้ว Download
  5. เปิดด้วย Android Studio หรือ Fleet
# หรือใช้ Command Line
# ติดตั้ง KMP Plugin สำหรับ Android Studio
# File > New > New Project > Kotlin Multiplatform

# Build and Run
./gradlew :shared:build              # Build Shared Module
./gradlew :androidApp:installDebug   # Run Android App
./gradlew :desktopApp:run            # Run Desktop App

# iOS — ต้องใช้ Xcode บน macOS
# เปิด iosApp/iosApp.xcodeproj แล้ว Run ใน Xcode
ต้องการ macOS สำหรับ iOS: การ Build iOS App ยังคงต้องใช้ macOS + Xcode แม้จะเขียน Kotlin Code บน Windows/Linux ก็ตาม นี่คือข้อจำกัดของ Apple ไม่ใช่ KMP สำหรับการทดสอบเบื้องต้น คุณสามารถใช้ CI/CD Service ที่มี macOS Runner ได้ เช่น GitHub Actions

สรุป — KMP คือ Future ของ Cross-Platform Development

Kotlin Multiplatform (KMP) กำลังเปลี่ยนวิธีที่นักพัฒนาคิดเกี่ยวกับ Cross-Platform Development แทนที่จะเลือกระหว่าง "Native Performance" กับ "Code Sharing" KMP ให้คุณได้ทั้งสองอย่าง คุณ Share Business Logic ที่ไม่เปลี่ยนตาม Platform (Networking, Database, Validation, Business Rules) และเขียน UI ที่ดีที่สุดสำหรับแต่ละ Platform

ในปี 2026 ด้วย Compose Multiplatform ที่เติบโตอย่างรวดเร็ว, Google Official Support, และ Ecosystem ที่ครบเครื่อง (Ktor, SQLDelight, Koin) KMP กลายเป็นตัวเลือก Cross-Platform ที่น่าจับตามองที่สุด ไม่ว่าคุณจะเป็น Android Developer ที่อยากขยายไป iOS, หรือ Startup ที่ต้องการ Launch ทุก Platform พร้อมกัน KMP คือเทคโนโลยีที่ควรลงทุนเรียนรู้อย่างจริงจัง

อ่านบทความเกี่ยวข้อง: Flutter Guide | React Native Guide | Mobile Architecture | Java/Spring Boot | Mobile Performance


Back to Blog | iCafe Forex | SiamLanCard | Siam2R