Kotlin 직렬화 시작하기
Kotlin 직렬화 시작하기
직렬화(Serialization)는 객체를 저장하거나 전송할 수 있는 형식으로 변환하고, 나중에 다시 재구성할 수 있게 해 주는 기법이에요.
Kotlin 직렬화는 여러 형식을 지원해요. 이 튜토리얼에서는 Kotlin 직렬화에 필요한 플러그인과 의존성을 추가하는 방법, 그리고 객체를 JSON 형식으로 직렬화·역직렬화하는 방법을 차근차근 보여 드릴게요.
본문
플러그인과 의존성 추가하기
프로젝트에 kotlinx.serialization 라이브러리를 포함하려면, 사용하는 빌드 도구에 맞춰 플러그인과 의존성 설정을 추가하면 돼요.
// build.gradle.kts
plugins {
kotlin("plugin.serialization") version "2.4.20"
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0")
}
// build.gradle
plugins {
id 'org.jetbrains.kotlin.plugin.serialization' version '2.4.20'
}
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0'
}
<!-- pom.xml -->
<properties>
<kotlin.version>2.4.20</kotlin.version>
<serialization.version>1.11.0</serialization.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<compilerPlugins>
<plugin>kotlinx-serialization</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-serialization</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-serialization-json</artifactId>
<version>${serialization.version}</version>
</dependency>
</dependencies>
Bazel의 Kotlin 컴파일러 플러그인을 설정하려면 rules_kotlin 저장소의 예시를 따라가면 돼요. Bazel은 Kotlin 팀이 공식 지원하지 않으며, 이 저장소는 독립적으로 관리되고 있어요.
멀티플랫폼 프로젝트에 라이브러리 추가하기
멀티플랫폼 프로젝트에서 JSON용 Kotlin 직렬화를 사용하려면, 공통 소스 셋(common source set)에 JSON 직렬화 라이브러리 의존성을 추가하면 됩니다.
commonMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0")
}
}
이 의존성은 핵심 직렬화 라이브러리도 자동으로 함께 포함시켜요.
Android 프로젝트에서 R8 구성하기
Kotlin 직렬화 라이브러리는 기본 ProGuard 규칙을 포함하고 있어서, 앱 축소(shrinking) 후에도 모든 직렬화 가능 클래스에 대한 직렬화기를 유지하기 위한 추가 설정이 필요 없어요. 다만 이 규칙은 이름이 있는 동반 객체(named companion object)를 가진 클래스에는 적용되지 않아요.
이름이 있는 동반 객체를 가진 클래스의 직렬화기를 유지하려면, 사용하는 호환 모드(compatibility mode)에 따른 규칙을 proguard-rules.pro 파일에 추가하면 됩니다.
# Serializer for classes with named companion objects are retrieved using getDeclaredClasses
# If you have any such classes, replace the examples below with your own
-keepattributes InnerClasses # Required for getDeclaredClasses
-if @kotlinx.serialization.Serializable class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions
com.example.myapplication.HasNamedCompanion2
{
static **$* *;
}
-keepnames class <1>$$serializer { # Using -keepnames is enough for the serializer() call to reference the class correctly
static <1>$$serializer INSTANCE;
}
# Serializer for classes with named companion objects are retrieved using getDeclaredClasses
# If you have any such classes, replace the examples below with your own
-keepattributes InnerClasses # Required for getDeclaredClasses
-if @kotlinx.serialization.Serializable class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions
com.example.myapplication.HasNamedCompanion2
{
static **$* *;
}
-keepnames class <1>$$serializer { # Using -keepnames is enough for the serializer() call to reference the class correctly
static <1>$$serializer INSTANCE;
}
# Keep both serializer and serializable classes to save the attribute InnerClasses
-keepclasseswithmembers, allowshrinking, allowobfuscation, allowaccessmodification class
com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions
com.example.myapplication.HasNamedCompanion2
{
*;
}
런타임에 절대 직렬화되지 않는 직렬화 가능 클래스들은, 더 좁은 클래스 스펙(class specifications)을 가진 커스텀 ProGuard 규칙으로 제외할 수 있어요.
객체를 JSON으로 직렬화하기
Kotlin에서는 kotlinx.serialization 라이브러리를 이용해 객체를 JSON으로 직렬화할 수 있어요.
클래스를 직렬화 가능하게 만들려면 @Serializable 어노테이션으로 표시해야 해요. 이 어노테이션은 컴파일러가 클래스 인스턴스를 직렬화·역직렬화하는 데 필요한 코드를 생성하도록 지시합니다. 자세한 내용은 @Serializable 어노테이션을 참고해 주세요.
예시를 하나 볼게요.
- 필요한 직렬화 라이브러리에서 선언을 임포트합니다.
import kotlinx.serialization.*
import kotlinx.serialization.json.*
- 클래스를
@Serializable로 표시해 직렬화 가능하게 만듭니다.
@Serializable
data class Book(val yearPublished: Int, val title: String)
@Serializable 어노테이션은 backing field를 가진 모든 프로퍼티의 기본 직렬화를 켜 줘요. 프로퍼티 레벨 어노테이션, 선택적 프로퍼티 등으로 직렬화 동작을 커스터마이즈할 수 있어요. 자세한 내용은 클래스 직렬화하기를 참고해 주세요.
Json.encodeToString()함수로 이 클래스의 인스턴스를 직렬화합니다.
// Imports declarations from the serialization and JSON handling libraries
import kotlinx.serialization.*
import kotlinx.serialization.json.*
// Marks the Book class as serializable
@Serializable
data class Book(val yearPublished: Int, val title: String)
fun main() {
// Serializes an instance of the Book class into a JSON string
val json = Json.encodeToString(Book(1937, "The Hobbit"))
println(json)
// {"yearPublished":1937,"title":"The Hobbit"}
}
그 결과로 이 객체의 상태를 JSON 형식으로 담은 문자열을 얻게 돼요: {"yearPublished":1937,"title":"The Hobbit"}
객체 컬렉션도 한 번의 호출로 직렬화할 수 있어요: val bookList = listOf(Book(1937, "The Hobbit"), Book(1867, "War and Peace")) 그다음 val jsonList = Json.encodeToString(bookList)처럼 쓰면 되죠.
객체를 JSON에서 역직렬화하기
역직렬화는 JSON 문자열을 다시 객체로 변환하는 과정이에요.
Kotlin에서 객체를 JSON에서 역직렬화하려면:
- 필요한 직렬화 라이브러리에서 선언을 임포트합니다.
import kotlinx.serialization.*
import kotlinx.serialization.json.*
- 클래스를
@Serializable로 표시해 직렬화 가능하게 만듭니다.
@Serializable
data class Book(val yearPublished: Int, val title: String)
Json.decodeFromString()함수로 객체를 JSON에서 역직렬화합니다.
// Imports declarations from the serialization and JSON handling libraries
import kotlinx.serialization.*
import kotlinx.serialization.json.*
// Marks the Book class as serializable
@Serializable
data class Book(val yearPublished: Int, val title: String)
fun main() {
// Deserializes a JSON string into an instance of the Book class
val obj = Json.decodeFromString<Book>("""{"yearPublished":1937, "title": "The Hobbit"}""")
println(obj)
// Book(yearPublished=1937, title=The Hobbit)
}
축하해요! 이제 객체를 JSON으로 직렬화하고, 다시 객체로 역직렬화하는 데 성공했어요.
더 알아보기
- 프리미티브, 문자열 같은 기본 타입과 일부 표준 라이브러리 클래스를 직렬화하는 방법은 내장 타입 직렬화하기에서 배울 수 있어요.
- 클래스 직렬화를 커스터마이즈하고
@Serializable어노테이션의 기본 동작을 조정하는 방법은 클래스 직렬화하기에서 알아볼 수 있어요. - JSON 데이터 처리를 더 깊이 파고들고 JSON 직렬화를 구성하는 방법은 JSON 직렬화 개요에서 다뤄요.