[시작하며 (반성)]
한 화면에서 다른 화면으로 이동할 때 데이터를 전달하려고하는 데, Primitive type 이 아닌 내가 만든 data class(디자인 패턴을 관점에서는 POJO 클래스, Model) 을 통째로 전달하고 싶을 수 있다.
액티비티 객체는 안드로이드 시스템에서 관리하는 컴포넌트로 데이터 전달에는 Intent 를 사용하기 때문!
그리고 최근에 Jetpack navigation 으로 프로젝트를 진행해왔는데, navigation 라이브러리에서도 Serializable 과 Parcelable 을 지원해서 Fragment 간 객체를 전달할 수 있었다.
Serializable 과 Parcelable 의 개념을 안드로이드 공부 시작하고 초반에 접하고 따로 더 공부한 적이 없이 자연스레 사용해서 잘 알고있다고 생각했는데,
최근에 면접을 보던 중 둘의 차이와 무엇을 쓸지 질문을 받았을 때 제대로 대답을 못하는 내 모습을 보고 반성하는 차원에서 글로 (코틀린 기준으로) 정리하려고 한다.
[직렬화 역직렬화]
- 직렬화란 메모리 상 정보를 Byte 단위의 코드를 통해 직렬로 나열하는 것
- 또한 내 객체 데이터를 네트워크로 전달하거나 데이터베이스에 저장하거나 파일로 만들 수 있는 포맷으로 바꿔주는 기술이다.
- 역직렬화란 직렬화의 반대로 변환된 데이터를, 즉 외부의 데이터를 다시 객체로 읽고 변환하는 기술이다.
[Serializable]
- 직렬화할 수 있게 해주는 인터페이스이다.
- 자바 표준 인터페이스 중 하나이고 안드로이드 SDK 에는 포함되어있지 않다.
- 장점
Serializeable 인터페이스만 상속하면 되므로 구현이 편리하다는 장점이 있다. - 단점
하지만 내부적으로는 자바의 리플렉션이 발생하게 되고 이로 인해 많은 오브젝트 생성과 그에 따른 Garbage Collection 이 발생하게 되어 안드로이드 앱의 성능을 낮추고 베터리를 더 잡아먹게된다는 단점이 있다! - 리플렉션이란 자바에서 제공하는 API 로, 생성되어 있는 객체를 통해 해당 객체의 클래스 정보를 분석하는 기법을 뜻한다. 따라서 직렬화, 역직렬화 할 때 리플렉션을 활용하면 그 과정에서 많은 객체를 생성하게 되고, 정보가 많아질 수록 GC 와 CPU 에 부담이 된다는 의미이다.
- 사용법은 아래 링크를 참고하자
[Parcelable, Parcelize]
- Parcelable 은 Parcel 로 쓰여지고 복원될 수 있는 객체를 가진 클래스들을 위한 인터페이스이다.
- 자바가 아닌 안드로이드 SDK 내에 포함되어있다.
- Parcel 은 IPC 전송에 높은 성능을 가지게 디자인 되어있다. 그래서 Parcel 데이터를 persistent storage 에 두는 것은 적절하지 않다. (Parcel 의 데이터 구현을 변경이 저장된 데이터를 읽을 수 없게하기 때문인듯?)
- Parcelable 인터페이스를 구현한 클래스는 CREATOR 라고 불리는 null 이 아닌 static 필드를 가져야한다.
- CREATOR 는 Parcelable.Creaator 인터페이스의 구현체이다.
- 장점
리플렉션을 사용하지 않게 설계되어있다. 그래서 Serializable 에서의 퍼포먼스 단점을 보완할 수 있다. - 단점
리플렉션을 없애기 위해 보일러플레이트 코드가 생겨 유지보수를 힘들 게 하는 요인이 된다.
class MyParcelable private constructor(`in`: Parcel) : Parcelable { private val mData: Int = `in`.readInt() override fun describeContents(): Int { return 0 } override fun writeToParcel(out: Parcel, flags: Int) { out.writeInt(mData) } companion object CREATOR: Parcelable.Creator<MyParcelable?> { override fun createFromParcel(`in`: Parcel): MyParcelable? { return MyParcelable(`in`) } override fun newArray(size: Int): Array<MyParcelable?> { return arrayOfNulls(size) } } } // https://developer.android.com/reference/android/os/Parcelable
- 단점 보완법
안드로이드 스튜디오(InteliJ IDE)의 Live Template 을 활용하면 쉽게 보일러플레이트 코드를 생성할 수 있다!
코틀린에서는 @Parcelize 를 사용하면 더욱 쉽게 Parcelable 을 구현할 수 있다. - @Parcelize 어노테이션을 사용한 Parcelable 구현 (자세한 내용은 코드 출처링크를 참고하자)
// build.gradle apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' ... import kotlinx.parcelize @Parcelize class User(val firstName: String, val lastName: String, val age: Int): Parcelable // 출처 https://www.charlezz.com/?p=44613
[결론]
- 안드로이드 프로젝트 진행 중에 객체를 어딘가에 담아서 보내야하는 경우 성능을 위해 Serialize 보다는 Parcelable 을 사용하자
- 보일러플레이트 코드를 줄이기 위해 @Parcelize 를 활용해보자!
[참고 링크]
'Android > 이론 학습' 카테고리의 다른 글
[Android] WorkManager 로 복잡한 백그라운드 작업을 쉽게 해결한다고? (기본 사용법과 예시코드 포함) (0) | 2022.02.23 |
---|---|
[Android] Service 의 타입과 사용법 그리고 권장사항 (0) | 2022.02.23 |
[Android] Hilt 의 다양한 어노테이션을 알아보자 (0) | 2022.02.19 |
[Android] 안드로이드의 DI (Dependency Injection) (0) | 2022.02.16 |
[Android] 안드로이드의 Background 작업 (0) | 2022.02.12 |