곰돌푸우❤️

목차

    안드로이드 컴포넌트나 Fragment간에 클래스로 데이터를 주고 받을 때 Serializable, Parcelable을 구현해야 합니다.

    직렬화/역직렬화, 마샬링/언마샬링 이라고도 하는 이 두 기법은 아주 빈번하게 사용됩니다. 

     

    Serializable은 Java의 표준 인터페이스 입니다.

    이 기법의 장점은 구현이 간편하다는점이 있습니다. 

    data class Person(
        var age: Int,
        var name: String,
        val birthday: String
    ) : Serializable

    위 코드처럼 일반 class 형태에서 Serializable만 구현하면 됩니다.

     하지만 단점으로는 Parcelable보다 속도가 느립니다. 왜냐하면 Serializable은 reflection이라는 기술을 사용기 때문입니다. 프로그램 런타임에 데이터를 직렬화/역직렬화하는 과정에 많은 객체를 생성하고 덕분에 GC가 할일이 늘어나게 됩니다. 그러면 아무래도 CPU에 부하가 가겠죠. 프로젝트의 사이즈가 커져서 Serializable을 사용하는 객체가 많아지면 많아질수록 성능에는 안좋은 영향을 미치게 됩니다.

     

    Parcelable은 Java가 아닌 Android SDK의 인터페이스입니다.

    이 기법은 Serializable보다 빠르고 Android에서 사용하기를 권장됩니다. Serializable과는 다르게 reflection을 사용하지 않고 직렬화/역직렬화를 하는 과정을 개발자가 모두 구현해주어야 합니다. 그렇게 구현된 코드가 미리 컴파일되어 런타임에 빠르게 처리됩니다. 런타임에 따로 객체를 여러개 생성하지 않으며 GC의 부담은 덜게되니 확실히 Serializable보다 나은 방법입니다.

     하지만 이 Parcelable의 단점을 꼽는다면 구현을 위한 보일러플레이트 코드가 늘어난다는 점입니다. 

    data class Person(
        var age: Int,
        var name: String,
        val birthday: String
    ) : Parcelable {
        constructor(parcel: Parcel) : this(
            parcel.readInt(),
            parcel.readString() ?: "",
            parcel.readString() ?: ""
        )
    
        override fun writeToParcel(parcel: Parcel, flags: Int) {
            parcel.writeInt(age)
            parcel.writeString(name)
            parcel.writeString(birthday)
        }
    
        override fun describeContents(): Int {
            return 0
        }
    
        companion object CREATOR : Parcelable.Creator<Person> {
            override fun createFromParcel(parcel: Parcel): Person {
                return Person(parcel)
            }
    
            override fun newArray(size: Int): Array<Person?> {
                return arrayOfNulls(size)
            }
        }
    }

    위의 Serializable과는 달리 늘어난 코드를 보실 수 있습니다. 직렬화를 위해 writeToParcel라는 메서드를 통해 Parcel객체에 데이터를 저장하고 역직렬화 할때에 createFromParcel이라는 메서드를 통해 Parcel로부터 데이터를 복원하고 Person객체를 다시 복원하게 됩니다. 이 모든 과정을 개발자가 직접 구현해야 한다는 부담은 있지만 미리 컴파일되어 런타임에 실행되니 reflection보다 확실히 성능상의 이점이 있습니다.

     

    Parcelize라는 기능이 코틀린에 등장했습니다.

    Serializable의 구현하기 쉬운 장점과 Parcelable의 성능상 이점을 모두 가질 수 있습니다.

    app/build.gradle

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    
    android {
        ...
        
        androidExtensions {
            experimental = true
        }
    }

    Person.kt

    @Parcelize
    data class Person(
        var age: Int,
        var name: String,
        val birthday: String
    ) : Parcelable

    클래스에 Parcelable을 구현하고 @Parcelize 어노테이션만 붙이면 끝입니다. parcelable의 필수메서드의 구현코드는 자동으로 생성되어 개발자가 신경쓰지 않아도 됩니다. 아직 실험적인 기능이지만 꽤 안정적으로 작동하고 있습니다. 

     

     안드로이드 개발에 Java로 개발하다가 Kotlin으로 개발언어를 바꾸고나서 코드량이 많이 줄었고 많은 기능에 흡족해 하고 있습니다. 직렬화도 꽤 자주 사용하는데 이 Parcelize 기능이 코틀린에 등장함으로써 개발을 더 편하게 하고 퍼포먼스를 더 향상시켜줄 것으로 보입니다. 

     

    모두들 일찍 퇴근하시고 즐코딩하세요!

    facebook twitter googleplus kakaostory naver