본문 바로가기
Android/Retrofit

[Android] 직렬화/역직렬화 라이브러리 (Gson, Moshi, Kotlin-serialization)

by 태크민 2025. 2. 20.

직렬화/ 역직렬화

Serialization(직렬화)란 자바 시스템 내부에서 사용하는 객체를 외부의 자바 시스템에서도 사용할 수 있도록 byte형태로 데이터를 변환시키는 기술을 말합니다.

안드로이드 상에선 직렬화를 이용해 액티비티간 또는 서비스간 클래스 타입의 데이터를 주고 받는 용도로 주로 사용합니다.

역직렬화(desrialization)는 그 반대로 디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 다시 변환하는 것입니다.

 

JSON 직렬화/역직렬화

JSON?

JSON은 JavaScript Object Notation의 약자로 Name과 Value로 이루어진 하나의 텍스트 형식입니다.

JSON은 언어로부터 독립적이기 때문에 다수의 언어(C, C++, C#, java, javaScript 등)간의 데이터 교환에 사용됩니다.

JSON에서는 기본적으로 key : value 형태로 데이터를 표현합니다, 또한 데이터들을 묶어 Object(중괄호 { }로 표기)와 Array(대괄호 [ ]로 표기) 형태로 표현합니다.

 


Gson vs Moshi vs Kotlin-serialization

대표적인 Converter Library 로는 Gson, Jackson, Moshi 등이 있습니다. 그리고 이는 모두 Java 언어로 개발되어 있습니다. 그리고 이는 모두 Java 언어로 개발되어 있습니다. Java로 구현되어 있다해서 코틀린에서 사용하지 못하는건 아니기 때문에 코틀린에서도 역시 이 라이브러리를 사용하고 계신 분들이 굉장히 많은데요. 그러나 완벽하게 호환된다고 하기에는 약간 아쉬운 부분들이 있습니다.

 

어떤 부분이 아쉬운지 코틀린의 data class 를 예로 들어보겠습니다.

먼저, User 라는 이름의 data class 를 정의해줍니다.

data class User (
    val name: String,
    val email: String,
    val age: Int = 20
)

 

아시다시피 코틀린의 data class 는 default value가 설정 가능하여, User 객체를 생성할 때 생성자에 age에 대한 값을 생략할 수 있고, 생략할 경우에 age 변수에는 기본 값으로 설정한 20이 설정됩니다. (자바에는 이런 문법이 없습니다.)

 

이 User 클래스를 두고 Gson과 Kotlinx.Serialization 의 결과를 비교해보도록 하겠습니다.

 

Gson

먼저 Gson을 통해 변환해보도록 하겠습니다.

fun main() {
    val jsonString = """
            {
                "name" : "Ready Kim",
                "email" : "ready.kim@gmail.com"
            }
        """.trimIndent()
 
    val user = Gson().fromJson(jsonString, User::class.java)
 
    println(user)
}

 

간단하게 JSON을 구성해서 "name" 과 "email" 필드만 지정해주고서 User 클래스로 변환하도록 코드를 작성해봤습니다.

위 코드를 실행하면 결과는 다음과 같이 나옵니다.

User(name=Ready Kim, email=ready.kim@gmail.com, age=0)

 

우리는 분명히 위에서 User 클래스를 작성할 때 age 프로퍼티의 default value로 20을 설정해줬습니다만, 변환된 결과를 보시면 제대로 설정이 안 된것을 확인할 수 있습니다.

 

즉, Gson은 코틀린의 default value 문법을 무시해버립니다. primitive 타입의 필드에 대해서는 0, refernce 타입의 필드에 대해서는 null 값을 기본으로 합니다. 주의할 점은 gson 컨버터는 코틀린의 null-safety 를 준수하지 않기 때문에 이에 대한 고려를 하지 않으면 Crash를 발생하게 됩니다.

그렇기 때문에 코틀린에서 Gson, Moshi 등을 사용할 때각 필드를 nullable 하게 설정해줘야 합니다. (Moshi에서는 이를 generateAdapter를 사용해서 gson의 단점을 보완가능)

이외에도 Gson은 리플렉션 기반으로 컴파일 타임이 아닌 런타임에 JSON을 변환하는 단점도 있다.

 

Kotlinx.Serialization

이번에는 코틀린에서 공식적으로 제공하고 있는 Kotlinx.Serialization 라이브러리를 사용해보겠습니다. 

일단 Kotlin Serialization 은 코틀린 언어를 만든 JetBrains 사에서 만들었으며, 다른 컨버터 언어들과는 다르게 Reflection을 사용하지 않고 개발한 라이브러리입니다. 리플렉션을 사용하지 않았기 때문에 성능상에서도 다른 컨버터 라이브러리에 비해 경쟁력을 갖습니다.

 

Kotlinx.Serialization의 사용법은 굉장히 간단합니다.

그냥 변환하고자 하는 클래스에 @Serializable 어노테이션만 추가해주면 됩니다. 이 어노테이션을 부착하고 나면 해당 클래스의 Companion Object의 serializer() 함수를 사용할 수 있게 됩니다. 그리고 이 함수가 반환하는 KSerializer 타입의 객체를 직렬화 작업에 사용하게 됩니다.

 

백문이 불여일코! 한 번 코드를 작성해보도록 하겠습니다.

 

Kotlin Serialization을 사용하기 위해서는 디펜던시를 추가해줘야 하는데, 이 부분은 Document를 참고하세요.

 

준비가 되었다면 코드를 작성해보겠습니다.

@Serializable
data class User (
    val name: String,
    val email: String,
    val age: Int = 20
)
 
fun main() {
    val jsonString = """
            {
                "name" : "Ready Kim",
                "email" : "ready.kim@gmail.com"
            }
        """.trimIndent()
 
    val user = Json.parse(User.serializer(), jsonString)
 
    println(user)
}

 

말씀드린것처럼 Kotlinx Serialization은 리플렉션을 사용하지 않기 때문에 User::class.java 타입의 파라미터를 사용하지 않았습니다.

실행 결과는 다음과 같습니다.

User(name=Ready Kim, email=ready.kim@gmail.com, age=20)

 

자! 이번에는 age에 20이 성공적으로 설정된 것을 확인할 수 있습니다.

 

글의 서론에서 언급한 것처럼 이런 컨버터 라이브러리는 REST API를 사용할 때 자주 필요로 하게 됩니다. 따라서, HTTP 통신에 사용되는 대표적인 라이브러리인 Retrofit 과 함께 사용하는 경우가 많은데요. 세계적인 네임드 개발자 Jake Wharton 형님이 Retrofit 과 호환되도록 Converter를 추가해주셨습니다. 문서를 참고하셔서 Retrofit 객체를 생성하실 때

Converter Factory 를 설정해주시면 레트로핏과도 함께 사용할 수 있습니다.

 

Moshi

Moshi는 Square에서 개발한 JSON Parser 라이브러리입니다. 

Gson과 유사하지만, 성능이 더 빠르고 코틀린과의 호환성이 더 높은 특징을 가지고 있습니다. 

Moshi 역시 Gson의 단점을 보완하여 코틀린 환경에서도 많이 사용하고 있습니다.

 

Moshi는 리플렉션을 우회하여 Gson의 성능 이슈를 보완합니다.

런타임에서 분석하는 리플렉션 방식과 달리 컴파일 시점에서 확인하기 때문에 처리속도가 빠르고 타입안전성이 높아지며, 프로가드 같은 도구로 축소 및 최적화하기 용이 합니다.

Moshi는 Codegen 어댑터를 통해 Json 데이터를 파싱하기 전에 미리 해당 데이터 클래스의 필드 타입 정보를 파악하여, 파싱할 때 매핑하여 사용합니다.

이 부분이 바로 Gson과의 가장 큰 차이를 만드는 부분입니다.

 

Gson은 런타임 시점에 클래스의 필드를 동적으로 검색하기 때문에 성능 문제가 발생하지만, Moshi는 이러한 정보들을 컴파일 타임에 미리 알아둬서 나중에 동적으로 검색할 때 발생하는 성능 문제를 해결했습니다.

따라서, Moshi는 Gson보다 훨씬 빠르고 메모리를 덜 사용합니다.

하지만, 리플렉션을 사용하지 않는 대신 별도 설정이 필요한 단점이 있습니다.

GSON vs Moshi

  • ❌ 코틀린 친화적이지 않다, null-safety같은 코틀린의 특징을 준수하지 않고 업데이트 또한 더딘 편이다.
    가장 최신 버전이 2.10.1버전 인데, 23.01.07에 나오고 이후 업데이트가 되지 않았다.
  • ❌ 메소드 수 또한 Moshi에 비해 거의 2배정도 차이 난다. (20년도 기준)
    그렇기 때문에 인터페이스가 복잡해지고, 성능 등 문제가 발생한다.
  • ❌ 용량 또한 차이가 나는대, Gson은 APK에 277KB (2.10.1 버전 기준), Moshi는 158KB ,코틀린 확장시 +19.8KB 177.8kb가 된다(1.15.1 버전 기준).
  • ❌ Gson은 리플렉션을 사용하여 JSON 문자열을 직렬화/역직렬화할 수만 있다.
    이게 왜 문제 냐면, 리플렉션은 런타임에 클래스의 메타데이터를 분석하기 때문에, 컴파일 시간에 코드를 최적화하는 것보다 성능이 떨어진다.
    또한 프로가드 같은 코드 축소 및 최적화가 힘들며, 보안또한 문제가된다.
    Moshi같은경우 Kotlin과 함께 사용할 때 코드 생성방식을 제공한다.
  • ❌ Gson은 필드에 대한 기본값을 지원하지 않는다. 응답 Json 문자열에 필드가 누락되고 해당 기본값을 null이 아닌 다른 값으로 설정해도 null이 된다.

GsonConverter는 Kotlin의 Null-safety와 Default value를 지원되지 않는다는 큰 문제점을 갖고 있습니다.

 


Good Performance

Moshi vs KotlinX Serialization — the ultimate benchmark

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

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

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


참고자료

https://medium.com/@ramkid91/%EC%A7%81%EB%A0%AC%ED%99%94-%EC%97%AD%EC%A7%81%EB%A0%AC%ED%99%94-gson-vs-moshi-69a022daf332

 

직렬화/역직렬화 , Gson vs Moshi

# 직렬화/ 역직렬화

medium.com

https://velog.io/@guysang/Moshi

 

Moshi

OkHttp, retrofit을 사용하면 안드로이드에서 Json파일을 직렬화 해서 사용해야한다.그럴때 컨버트 라이브러리로 주로 Gson을 사용했는데, 요즘 잘 안쓴다고 한다.20년도에 Jake Wharton이 말하길 개발자 3

velog.io

https://everyday-develop-myself.tistory.com/348

 

안드로이드에서 Json을 사용하는 다양한 방법

사진: Unsplash의Arisa Chattasa 안드로이드 개발을 하면서 서버에서 데이터를 받아와야 하는 경우가 상당히 많이 발생합니다. 이때 서버에서 보내주는 데이터의 형식은 대부분 JSON 데이터 형식으로

everyday-develop-myself.tistory.com

https://readystory.tistory.com/177

 

Kotlinx Serialization - 코틀린에 가장 적합한 Json Converter

아마 REST API를 구현해보신 분이라면 JSON 데이터를 다뤄보신 경험이 있으실 겁니다. 개발을 하다보면 JSON 이나 XML 등을 다뤄야하는 경우가 자주 발생하는데요. 기본적으로 JSON 이나 XML 은 JVM 언어

readystory.tistory.com