출시·고도화 중
Kotlin 안내서 · 4/6
프로그램이 커지면 코드를 파일과 패키지로 나누고, 외부 라이브러리를 가져다 써야 합니다. 이 장에서는 Kotlin의 패키지와 import, 가시성 규칙, Gradle로 의존성을 추가하는 방법, 그리고 Kotlin Multiplatform을 간단히 소개합니다.
파일 맨 위의 package 선언이 그 파일에 있는 모든 선언의 이름 공간을 정합니다. Java와 달리 한 파일에 클래스를 여러 개 두어도 되고, 클래스 밖에 함수나 속성을 바로 선언할 수도 있습니다.
// src/main/kotlin/com/example/shop/Order.kt
package com.example.shop
data class Order(val id: Long, val amount: Int)
fun totalOf(orders: List<Order>): Int = orders.sumOf { it.amount }
const val FREE_SHIPPING_MIN = 50_000Kotlin은 디렉터리 구조가 패키지 이름과 꼭 같을 필요는 없지만, 같게 맞추는 것이 공식 권장 사항입니다. package 선언이 없으면 이름 없는 기본 패키지에 들어갑니다.
다른 패키지의 선언은 import로 가져옵니다. 클래스뿐 아니라 최상위 함수와 속성도 가져올 수 있고, 이름이 겹치면 as로 별칭을 붙입니다.
package com.example.app
import com.example.shop.Order
import com.example.shop.totalOf
import com.example.shop.FREE_SHIPPING_MIN
import com.example.legacy.Order as LegacyOrder
import java.time.LocalDate
fun main() {
val orders = listOf(Order(1, 30_000), Order(2, 42_000))
val total = totalOf(orders)
println("${LocalDate.now()} 합계: $total")
println("무료 배송: ${total >= FREE_SHIPPING_MIN}")
}import com.example.shop.*처럼 패키지 전체를 가져올 수도 있습니다. kotlin.*, kotlin.collections.*, kotlin.text.*, kotlin.io.*, kotlin.ranges.* 같은 패키지는 기본으로 import 되어 있고, JVM에서는 java.lang.*도 마찬가지입니다. 그래서 listOf나 println은 import 없이 쓸 수 있습니다.
| 변경자 | 최상위 선언 | 클래스 멤버 |
|---|---|---|
public(기본값) | 어디서나 | 어디서나 |
internal | 같은 모듈 안 | 같은 모듈 안 |
protected | 쓸 수 없음 | 그 클래스와 하위 클래스 |
private | 같은 파일 안 | 그 클래스 안 |
아무것도 적지 않으면 public입니다. internal의 모듈은 함께 컴파일되는 파일 묶음으로, 보통 Gradle 모듈 하나(정확히는 그 소스 세트)를 뜻합니다. 라이브러리를 만들 때 외부에 보여 줄 필요가 없는 구현은 internal로 감추면 됩니다.
Kotlin 라이브러리는 대부분 Maven Central 저장소에 올라와 있습니다. 라이브러리는 그룹:아티팩트:버전 형식의 좌표로 가리킵니다. 최근 Gradle 프로젝트는 버전을 버전 카탈로그 파일에 모아 두는 방식을 씁니다. 아래 x.y.z는 실제로 쓸 버전으로 바꿉니다.
# gradle/libs.versions.toml
[versions]
kotlin = "x.y.z"
coroutines = "x.y.z"
[libraries]
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }// build.gradle.kts
plugins {
alias(libs.plugins.kotlin.jvm)
}
repositories {
mavenCentral()
}
dependencies {
implementation(libs.kotlinx.coroutines.core) // 카탈로그 사용
implementation("com.squareup.okhttp3:okhttp:x.y.z") // 좌표를 직접 적는 방식
testImplementation(kotlin("test"))
}implementation은 컴파일과 실행에 모두 필요한 의존성, testImplementation은 테스트에만 필요한 의존성, runtimeOnly는 실행할 때만 필요한 의존성입니다. 라이브러리와 최신 버전은 Maven Central에서 찾을 수 있고, ./gradlew dependencies를 실행하면 실제로 끌려온 의존성 나무를 볼 수 있습니다.
프로젝트가 커지면 Gradle 모듈 여러 개로 나눕니다. settings.gradle.kts에 모듈을 등록하고, 다른 모듈을 의존성으로 추가합니다.
// settings.gradle.kts
rootProject.name = "shop"
include(":core", ":app")
// app/build.gradle.kts 의 dependencies 블록 안
// implementation(project(":core"))이렇게 나누면 core의 internal 선언은 app에서 보이지 않으므로, 모듈 사이의 경계가 컴파일러로 지켜집니다.
Kotlin Multiplatform(KMP)은 한 코드베이스의 공통 로직을 JVM, Android, iOS(Kotlin/Native), 브라우저(Kotlin/JS, Kotlin/Wasm) 등 여러 플랫폼에서 함께 쓰게 해 주는 기술입니다. 공통 코드는 commonMain 소스 세트에 두고, 플랫폼마다 다른 부분은 jvmMain, iosMain 같은 소스 세트에 둡니다. 공통 코드에서 expect로 선언하고 각 플랫폼에서 actual로 구현합니다.
// commonMain
expect fun platformName(): String
fun greeting() = "Hello from ${platformName()}"
// jvmMain
actual fun platformName(): String = "JVM"KMP를 쓰면 화면은 플랫폼마다 따로 만들고 비즈니스 로직만 나눠 쓸 수도 있고, Compose Multiplatform으로 화면까지 함께 쓸 수도 있습니다. 처음 배울 때는 JVM 프로젝트로 시작하고, 필요해지면 KMP를 살펴보는 것을 권합니다.
package로 이름 공간을 정하고, 한 파일에 클래스와 최상위 함수를 여러 개 둘 수 있습니다.import는 클래스와 최상위 함수 모두에 쓰며, as로 별칭을 붙입니다.public이고, internal은 같은 모듈 안에서만 보입니다.build.gradle.kts의 dependencies에 좌표나 버전 카탈로그로 추가하고, 주로 Maven Central에서 받습니다.expect/actual로 플랫폼별 구현을 나누어 여러 플랫폼에서 코드를 함께 씁니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.