KMP 프로젝트 구조: commonMain, androidMain, iosMain
소스 세트 계층 구조와 여러 대상 간에 코드를 공유하는 방법을 이해해 보세요.
KMP 프로젝트 구조: commonMain, androidMain, iosMain은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
KMP란 무엇인가요
Kotlin Multiplatform(KMP)을 사용하면 여러 플랫폼에서 공유할 Kotlin 코드를 작성할 수 있으며, 이 코드는 JVM, Android, iOS(Kotlin/Native를 통해), JS용으로 컴파일됩니다. 플랫폼별 코드는 별도의 소스 세트에 둡니다.
// Typical KMP module structure:
// shared/
// src/
// commonMain/kotlin/ <- shared code
// androidMain/kotlin/ <- Android-only
// iosMain/kotlin/ <- iOS-only
// commonTest/kotlin/ <- shared tests
fun main() { println("KMP: one codebase, many targets") }소스 세트 계층 구조
소스 세트는 계층 구조를 이룹니다. commonMain이 루트이고 androidMain과 iosMain이 이에 의존합니다. commonMain의 코드는 모든 대상에서 사용할 수 있습니다.
// build.gradle.kts (Kotlin DSL)
kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val commonMain by getting {
dependencies { /* shared deps */ }
}
val androidMain by getting
val iosMain by getting
}
}commonMain: 공유 로직
비즈니스 로직, 도메인 모델, 저장소, 유스 케이스를 commonMain에 배치합니다. 이 코드는 모든 대상용으로 컴파일됩니다.
// commonMain/kotlin/com/example/domain/User.kt
data class User(val id: String, val name: String, val email: String)
// commonMain/kotlin/com/example/repository/UserRepository.kt
interface UserRepository {
suspend fun getUser(id: String): User?
suspend fun saveUser(user: User)
}androidMain: Android 전용
androidMain에서는 Android SDK 클래스를 사용할 수 있습니다. 일반적인 용도는 expect/actual 선언의 Android 전용 구현입니다.
// androidMain/kotlin/com/example/platform/PlatformLogger.kt
import android.util.Log
class AndroidLogger : Logger {
override fun log(msg: String) = Log.d("App", msg)
}
// androidMain/kotlin/com/example/di/PlatformModule.kt
// Koin or Hilt module that binds AndroidLogger to LoggeriosMain: iOS 전용
iosMain에서는 Kotlin/Native 상호 운용을 통해 Apple 프레임워크에 접근할 수 있습니다. expect/actual API의 iOS 구현에 사용합니다.
// iosMain/kotlin/com/example/platform/PlatformLogger.kt
import platform.Foundation.NSLog
class IosLogger : Logger {
override fun log(msg: String) = NSLog(msg)
}
// iOS uses Kotlin/Native runtime; no JVM hereiOS 대상의 Gradle 구성
iOS에서는 일반적으로 세 가지 대상을 선언합니다. x64는 Intel 시뮬레이터용이고, arm64는 기기용이며, simulatorArm64는 Apple Silicon 시뮬레이터용입니다.
// build.gradle.kts
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val iosMain by creating {
dependsOn(commonMain.get())
}
val iosX64Main by getting { dependsOn(iosMain) }
val iosArm64Main by getting { dependsOn(iosMain) }
val iosSimulatorArm64Main by getting { dependsOn(iosMain) }
}
}commonMain의 공유 종속성
공유 종속성(Ktor, SQLDelight, kotlinx.serialization, Koin)을 commonMain에 추가합니다. 플랫폼별 드라이버는 플랫폼 소스 세트에 배치합니다.
// commonMain dependencies example:
// implementation("io.ktor:ktor-client-core:2.3.0")
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// implementation("io.insert-koin:koin-core:3.4.0")
// androidMain:
// implementation("io.ktor:ktor-client-okhttp:2.3.0")
// iosMain:
// implementation("io.ktor:ktor-client-darwin:2.3.0")commonTest: 공유 테스트
commonTest의 테스트는 모든 대상에서 실행됩니다. Kotlin 테스트 라이브러리를 사용하고 공유 비즈니스 로직을 대상으로 특정 플랫폼에 종속되지 않는 단위 테스트를 작성합니다.
// commonTest/kotlin/UserRepositoryTest.kt
import kotlin.test.Test
import kotlin.test.assertEquals
class UserRepositoryTest {
@Test
fun testUserCreation() {
val user = User("1", "Alice", "alice@example.com")
assertEquals("Alice", user.name)
}
}중간 소스 세트
일부 대상에서 공유되는 중간 소스 세트를 만들 수도 있습니다. 예를 들어 nativeMain은 모든 네이티브 대상에서, appleMain은 iOS와 macOS에서 공유됩니다.
// Create appleMain shared between iOS and macOS:
sourceSets {
val appleMain by creating { dependsOn(commonMain.get()) }
val iosMain by getting { dependsOn(appleMain) }
val macosMain by getting { dependsOn(appleMain) }
}프로젝트 파일 배치
관심사를 명확하게 분리한 일반적인 KMP 공유 모듈 디렉터리 트리입니다.
// shared/
// build.gradle.kts
// src/
// commonMain/kotlin/
// domain/ User.kt, Post.kt
// repository/ UserRepository.kt
// usecase/ GetUserUseCase.kt
// androidMain/kotlin/
// repository/ RoomUserRepository.kt
// iosMain/kotlin/
// repository/ CoreDataUserRepository.kt
// commonTest/kotlin/ GetUserUseCaseTest.ktCocoaPods / SPM 통합
KMP Gradle 플러그인은 XCFramework(또는 CocoaPods pod)를 생성합니다. 이를 Xcode 프로젝트에 추가하면 공유 Kotlin 코드가 네이티브 프레임워크로 노출됩니다.
// build.gradle.kts for CocoaPods:
kotlin {
cocoapods {
name = "Shared"
version = "1.0"
ios.deploymentTarget = "14.0"
framework { baseName = "Shared" }
}
}
// Run: ./gradlew :shared:podPublishReleaseXCFramework빠른 확인
KMP 프로젝트에서 공유 비즈니스 로직(도메인 모델, 유스 케이스)은 어디에 배치해야 합니까?
정리
commonMain에는 공유 로직(도메인, 저장소, 유스 케이스)이 들어갑니다. androidMain/iosMain에는 플랫폼 구현이 들어갑니다. commonTest는 모든 대상에서 테스트를 실행합니다. 종속성은 분리하여, 공유 API는 commonMain에, 플랫폼 드라이버는 플랫폼 소스 세트에 둡니다.
자주 묻는 질문
“KMP 프로젝트 구조: commonMain, androidMain, iosMain” 강의는 무료인가요?
네 — “KMP 프로젝트 구조: commonMain, androidMain, iosMain” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“KMP 프로젝트 구조: commonMain, androidMain, iosMain”에서 뭘 배우나요?
소스 세트 계층 구조와 여러 대상 간에 코드를 공유하는 방법을 이해해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“KMP 프로젝트 구조: commonMain, androidMain, iosMain” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- KMP 프로젝트 구조: commonMain, androidMain, iosMain
- 플랫폼 API를 위한 expect/actual 메커니즘
- 저장소 및 사용 사례 계층 공유하기
- Koin을 사용한 KMP 의존성 주입