Beeeam

직렬화, 역직렬화, Kotlin Serialization 본문

Kotlin

직렬화, 역직렬화, Kotlin Serialization

Beamjun 2024. 1. 22. 19:23

최근에 Jetpack Compose를 사용하여 프로젝트를 진행하고 있다. 근데 Navigation을 사용하여 화면 이동을 구현하는 과정에서 data class로 정의된 객체를 전달 해야하는 상황이 생겼다. 화면 이동하면서 인자를 전달하는 방법에 대해서 찾아봤는데 전부 String 타입으로 전달해야 한다는 내용들이였다.

근데 현재 내가 처한 상황은 String 타입이 아닌 커스텀 타입의 객체를 전달하는 것이였다. 이에 대해서도 찾아보니 전달하고자 하는 객체를 직렬화 하고 커스텀 NavType을 사용하라는 답을 발견했다.

결론부터 말하면 커스텀 NavType을 사용하는 방법으로 해결하지 못했다… 인자의 타입을 커스텀 NavType으로 설정하면 화면 이동이 안되는 오류가 발생했다…

그래서 생각하던 중 String 타입으로 전달하면 오류가 발생하지 않으니 아예 값을 전달하기 전에 직렬화 해서 String 타입으로 변환하고 받는 쪽에서 이를 역직렬화하면 되지 않을까 라는 생각을 하게되었고 이 방법으로 해결하였다.

 

사실 이 전까지 직렬화에 대해서 듣기만 했었다. 직렬화의 필요성을 제대로 느낀건 이번이 처음인 거 같다. 그래서 직렬화, 역직렬화에 대해서 찾아보고 정리를 하려고 한다.

 

직렬화 vs 역직렬화

https://kotlinlang.org/docs/serialization.html#libraries

 

Serialization | Kotlin

 

kotlinlang.org

 

코틀린 공식 문서에서는 직렬화를 다음과 같이 설명하고 있다.

Serialization is the process of converting data used by an application to a format that can be transferred over a network or stored in a database or a file.


쉽게 말해 우리가 사용하는 String, Int, Float 등의 타입 데이터를 Json, Gson 등의 타입으로 변환하는 것이다.

역직렬화는 직렬화의 반대 개념이다.

 

Deserialization is the opposite process of reading data from an external source and converting it into a runtime object.


파일 형태의 데이터를 우리가 사용하는 타입으로 변환하는 것
이다.

 

직렬화 라이브러리

직렬화는 Gson이나 Moshi 라이브러리를 사용하여 구현할 수 있다고 한다.

Gson

A Java serialization/deserialization library to convert Java Objects into JSON and back


Gson은 Retrofit을 사용했다면 한번쯤은 봤을 것이라 생각한다. 설명을 읽어보면 “자바” 라는 단어를 볼 수 있다. 자바 기반이기 때문에 코틀린 친화적이지 않을 수 있다.

그리고 2008년 이후로 업데이트가 되고 있지 않아서 최신의 기술이 아니다.

Moshi

Moshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin classes


Moshi는 설명부터 코틀린에도 친화적인 것을 알 수 있다. 그리고 Gson에 비해 메서드의 개수가 절반 밖에 안된다. 이 때문에 APK의 크기를 줄일 수 있는 장점이 있다.

 

이런 라이브러리들이 있지만 Kotlin Serialization 라이브러리를 알아보고자 한다.

 

Kotlin Serialization

위의 두 라이브러리 중 골라서 사용하면 될거 같은데 왜 Kotlin Serialization을 사용할까?

1. Kotlin Serialization is made by jetBrains

코틀린을 만든 Jetbrains에서 만든 라이브러리이다. 그래서 코틀린에 친화적이다.

Gson을 사용하면 data class의 default 값이 무시되는 오류가 생기곤 했는데 Kotlin Serialization에서는 그런 문제가 발생하지 않는다.

2. Safe Complie

Kotlin Serialization은 @Serialization 어노테이션이 붙은 클래스만 직렬화 하기 때문에 오류가 발생하면 런타임 에러가 아닌 컴파일 에러를 발생시켜 버그를 예방한다.

3. Good Performance

Moshi vs KotlinX Serialization — the ultimate benchmark

 

Moshi vs KotlinX Serialization — the ultimate benchmark

Moshi and KotlinX Serialization are solutions commonly used in Kotlin language to work with data in JSON format. I’ve decided to look at…

medium.com

위의 글에서는 Moshi와 Kotlin Serialization의 성능 비교를 했다.

일반적인 모델, 크기가 큰 모델, Sealed class로 나눠서 각각의 직렬화, 역직렬화 시간을 측정하고 분석하였는데 3개 모두 Kotlin Serialization이 더 빠르다는 결론이 나왔다.

Moshi는 코틀린에 덜 친화적이라서 몇몇 버전에서는 사용할 수 없다는 결론도 확인할 수 있다.

 

위와 같은 이유들 때문에 Kotlin Serialization 라이브러리를 알아보았다.

그럼 이제 사용법을 알아보자

How to use Kotlin Serialization

먼저 의존성을 추가한다.

(저는 IntelliJ에서 테스트 했기 때문에 안드로이드 스튜디오에 적용하는 것과 다릅니다!)

build.gradle에 다음과 같이 추가한다.

plugins {
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.serialization") version "1.9.22"
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
}

이렇게 하면 사용할 준비는 끝났다.

Example

직렬화 하고자 하는 클래스에 @Serialization 어노테이션을 붙이면 이 클래스를 직렬화, 역직렬화 할 수 있다.

@Serializable
data class Sample(
    val a: String,
    val b: Int = 1,
    val c: String = "sample!",
)

 

직렬화 하고 싶으면 encodeToString() 함수를, 역직렬화 하고 싶으면 decodeFromString() 함수를 사용하면 된다.

fun main(args: Array<String>) {
    val stringToJson = Json.encodeToString(Sample("a", 2, "Sample!"))
    println(stringToJson)

    val jsonToString: Sample = Json.decodeFromString(stringToJson)
    println(jsonToString)
}

// 실행 결과
// {"a":"a","b":2,"c":"Sample!"}
// Sample(a=a, b=2, c=Sample!)

 

위에서 언급했던 data class default 값을 지원하는 것도 확인할 수 있다.

fun main(args: Array<String>) {
    val data = """
        {
            "a" : "aaaa!"
        }
    """
    val dataToString: Sample = Json.decodeFromString(data)
    println(dataToString)
}

// 실행 결과
// Sample(a=aaaa!, b=1, c=sample!)

 

만약 직렬화 하고자 하는 클래스에 @Serialization 어노테이션을 붙이지 않으면 다음과 같은 메시지를 보여주면서 컴파일 에러가 발생하는 것도 확인할 수 있다.

Exception in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'Sample' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.