이전에 객체를 전달하기 위해 Parcelable을 상속받아 Parcelable객체를 만들어 사용하는 방법에 대해서 포스팅했었다.
Parcelable을 사용하는 이유는 객체 전달시 객체 직렬화 필요하기 때문인데 직렬화는 객체가 갖고 있는 다양한 변수들을 하나의 Byte 별 형태로 만드는 작업이라고 배웠다.
Parcelable 인터페이스를 상속받고 메서드 오버라이딩을 통해 객체 -> Parcel, Parcel -> 객체 의 변환 과정을 명시적으로 구현 한다.
그런데 새로운 프로젝트를 진행하며 retrofit을 사용하게 되었고 자연스럽게 객체를 송수신하기 위해서 직렬화와 관련된 기술에 대해 더 찾아보던 중 Serializable에 대해서 알게 되었다.
Serializable
- 표준 JAVA 인터페이스
- 내부적으로 reflection을 사용하기 때문에 개발자가 복잡한 구현없이 간단하게 사용하기에 쉽다
- 사용하지 않는 객체들은 가비지 컬렉터가 열일하면서 정리해주기 때문에 앱의 성능이 낮아질 수 있다
- Gson 라이브러리 사용
Parcelable
- 안드로이드 SDK가 포함하고 있는 인터페이스
- serializable이 해줬던 reflection을 사용하지 않도록 되어있기 때문에 개발자가 오버라이딩해서 구현해줘야 할 메서드가 많다
- serializable에 비해 속도가 빠르다고 한다 (직접 성능 비교를 해보진 않음...)
일단 Parcelable 과 Serializable 둘 다 객체를 전달하고자 할 때 사용할 수 있다.
- 액티비티 간에 객체를 전달할 때
- 서버로부터 데이터를 송수신할 때
모두 직렬화와 역직렬화 과정이 필요하기 때문에 해당 방법을 사용할 수 있다
내가 프로젝트에서 parcleable 과 serializable에 대해 더 공부하게 된 계기는 서버와 데이터를 송수신하기 위한 방법을 공부하면서였다. 서버로부터 데이터를 송수신 할 때는 Json 형태로 주고 받는데 json 데이터를 그대로 받아 직접 하나하나 다 파싱해 사용하는 것이 아닌 데이터를 받아왔을 때 바로 매핑할 수 있도록 해주는 것이 편리하다.
이것을 구현하기 위한 방법을 DTO(Data Transfer Object);데이터 전송 객체 라고 부르는데 이 과정에서도 직렬화가 필요하기 때문에 Parcelable 이나 Serializable를 상속받아 구현해 사용하는 것이다.
일반 클래스를 만들고 Parcelable 이나 Serializable를 상속받아 DTO를 구현할 수도 있지만 상당히 귀찮기 때문에 코틀린에서 제공하는 data class를 활용하기로 했다.
Data Class 는 직렬화를 제공하기 때문에 따로 Serializable 등을 상속받지 않아도 된다. 다만 @SerializedName 어노테이션을 활용해 Json의 키 값과 필드를 명시적으로 정의하면 좋다.
나의 경우 data class를 사용해 DTO를 만들어 서버와 데이터 송수신에서 사용하고, 화면 이동시 객체 전달에도 사용하려고 했다.
처음에는 객체 전달을 위해서는 무조건 parcelable를 상속받아 메서드 오버라이딩을 구현해야 한다고 생각했는데 이 과정이 너무 귀찮았다. 그래서 찾던 중 구현이 간단한 serializable을 상속받아 사용하기로 했다.
그런데 Serializable 객체는 intent시 객체 전달이 불가능했다. Serializable 객체도 객체 전달시 사용되는 직렬화 인터페이스인데 왜 안 되는지 잘 모르겠다...... 에러 메세지에서는 Parcelable을 사용해야 객체 전달을 할 수 있다고 나와있었다.
=> 이는 Serializable 인터페이스가 액티비티 전환을 위한 객체 직렬화에 적합하지 않기 때문이라고 한다. Serializable 인터페이스는 Java 시리얼라이제이션 메커니즘이기 때문에 안드로이드 intent 객체 전달에 적합하지 않은 것 같다. 근데 다른 블로그에서도 그렇고 Serializable를 상속받은 data class객체를 intent의 Extra에 넣어서 전달하고 getSerializeExtra()로 전달받아 잘만 사용했는데 버전업 되면서 이젠 막은건지 난 계속 에러가 났다......흠 잘 모르겠다.....
그런데 다행스럽게도 data class는 컴파일러가 자동으로 Parcelable 인터페이스를 구현해주기 때문에 메서드 오버라이딩을 직접 작성할 필요가 없었다. 대신 @Parcelize 어노테이션을 적어주고 Parcelable 인터페이스를 상속받도록 작성해주면 된다.
무튼 나는 액티비티 변환시 객체 전달 + 데이터 송수신 DTO 객체 생성 이라는 2가지 요구사항을 모두 만족할 수 있었다.
@Parcelize
data class PhotoSpotItemDTO (
@SerializedName("photoSpotId")
val photoSpotId : Int,
@SerializedName("photoSpotName")
val photoSpotName : String?,
@SerializedName("photoSpotImage")
val photoSpotImage : URL,
@SerializedName("hashtags")
val hashtags : List<String>,
@SerializedName("photoGuideNum")
val photoGuideNum : Int,
@SerializedName("myDistance")
val myDistance : Int
) : Parcelable
val getPhotoIntent: Intent = intent
val selected_obj_item = getPhotoIntent.getParcelableExtra<PhotoGuidesDTO>("selected_guide_item")
💡 간단 정리
- DTO를 구현하고 싶다 -> data class 를 사용하여 @SerializedName 를 붙여주자
- DTO 객체를 intent에 담아 전달하고 싶다 -> Parcelable을 상속받고, @Parcelize를 붙여주자
[참고자료]
https://developer.android.com/kotlin/parcelize?hl=ko
https://wooooooak.github.io/android/2019/09/19/Serializable-vs-Parcelable/
https://velog.io/@ddanglehee/Android-DTO%EC%99%80-Entity-%EA%B7%B8%EB%A6%AC%EA%B3%A0-DAO
'Android' 카테고리의 다른 글
[안드로이드/아키텍쳐] AAC ViewModel 사용하기 (0) | 2023.07.13 |
---|---|
[안드로이드/아키텍쳐] MVC, MVVM 패턴 그리고 ViewModel (0) | 2023.07.13 |
[안드로이드/소셜로그인&Oauth] AWS와 통신하는 안드로이드 앱에서 Google Oauth2.0 사용하기 (4) | 2023.07.13 |
[안드로이드/센서] GPS 사용하기 (0) | 2023.05.16 |
[안드로이드/Oauth/Error] Google Oauth2.0 파이어베이스 없이 사용하기 & ApiException 10 에러 해결 (2) | 2023.05.13 |