본문 바로가기
Android

[Android] 직렬화와 Serializable, Parcelable

by 태크민 2024. 12. 17.

직렬화, 역직렬화

  • 직렬화(Serialization) : 객체를 바이트 단위의 연속적 데이터(바이트 스트림)로 변경하는 작업
  • 역직렬화(Deserialization) : 바이트 스트림을 원래 객체로 변환하는 작업

 

왜 직렬화가 필요한가 ?

데이터를 서버 등으로부터 받아올 때 보통 JSON, XML 등의 형태가 전달되곤 합니다.

이 때, 이를 역직렬화하여 바로 기존 객체처럼 쓸 수 있게하거나, JVM 메모리에만 상주되어있던 그런 객체들을 영속화 (Persistence)시켜 시스템이 종료되더라도 없어지지 않게끔 처리해야할 때(Shared Prefrence / DB 등) 직렬화를 사용합니다.

 

Android Intent 통신 과정에서 직렬화

안드로이드의 경우 Intent를 통해 객체를 주고 받습니다.

Intent는 프로세스 간 통신을 할 수 있도록 설계되었기 때문에 IPC라는 방법을 사용하고, IPC는 byte형식으로 전송이 가능하기 때문에 byte코드로 직렬화하는 과정이 필요한 것입니다.

 

기본 데이터 타입은 왜 직렬화를 안할까요?

기본 데이터 타입은 바이트 단위로 처리가 되고 전달되어 (안드로이드 시스템에의해) 직렬화가 필요없습니다.

하지만 객체는, 바이트 단위로 처리가 되지 않으므로 직접 직렬화를 해주어야 합니다.


 

Serializable, Parcelable

안드로이드 앱을 개발할 때 종종 하나의 액티비티 에서 다른 액티비티 로 데이터를 전달하기 위해 인텐트에 전달할 데이터를 추가 합니다.

복잡한 클래스의 객체를 이동하려는 경우 Serializable 또는 Parcelable 를 사용하여 직렬화 하여 인텐트에 추가 해야 합니다.

Serializable 이란 무엇인가?

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

이 인터페이스를 구현한 클래스의 객체는 이제 한 액티비티 에서 다른 액티비티 로 이동할 준비가 됩니다. 다음 코드에서 이 인터페이스를 사용하는 것이 얼마나 간단한 지 알 수 있습니다.

 

Serializable 은 해당클래스가 직렬화 대상이라고 알려주기만 할뿐 어떠한 메서드도 가지지 않는 단순한 “마커 인터페이스 (Marker Interface)” 이므로, 사용자는 매우 쉽게 사용할 수 있습니다.

사용방법이 쉽다는 것은 곧 시스템 적인 비용이 비싸다는것을 의미 합니다.

Serializable 은 내부에서 Reflection 을 사용하여 직렬화를 처리합니다. Reflection 은 프로세스 동작 중에 사용되며 처리 과정 중에 많은 추가 객체를 생성 합니다. 이 많은 쓰레기들은 가비지 컬렉터의 타겟이 되고 가비지 컬렉터의 과도한 동작으로 인하여 속도성능 저하배터리 소모가 발생합니다.

 

리플렉션은 뭘까요?

객체를 통해 클래스의 정보를 분석해 내는 프로그래밍 기법을 말합니다. 
리플렉션은 구체적인 클래스 타입을 알지 못해도 컴파일된 바이트 코드를 통해 그 클래스의 메소드, 타입, 변수 들을 접근할 수 있도록 해주는 자바 API입니다.
(프로그램 실행 중에 객체를 동적으로 조작할 수 있는 기능을합니다.)

리플렉션은 속도를 저하시키기에 구글에서 권장하지 않습니다.

 

Parcelable 은 무엇인가?

Parcelable 은 직렬화를 위한 또다른 인터페이스 입니다. Serializable 과는 달리 표준 Java 가 아닌 Android SDK 의 인터페이스 입니다.

Parcelable 은 Reflection 을 사용하지 않도록 설계되었습니다. Serializable 과는 달리 직렬화 처리 방법을 사용자가 명시적으로 작성하기 때문에 자동으로 처리하기 위한 Reflection 이 필요 없습니다. 

따라서, Reflection을 사용하지 않아 런타임 시 객체 생성할 필요가 없어 GC의 부담이 없어지고, 속도 성능이 좋습니다.

다음의 코드 에서 Parcelable 인터페이스의 사용법을 볼 수 있습니다.

 

물론, Parcelable 을 사용할 때 지불해야하는 비용도 있습니다.

마커 인터페이스 인 Serializable 과는 달리 Parcelable 은 구현 해야 하는 필수 메서드를 포함 하기 때문에 클래스에 보일러 플레이트 코드 가 추가 됩니다. 이는 클래스 를 이해 하기 어렵고, 새로운 기능을 추가 하기 힘들게 만듭니다. 또한 코드의 추가로 클래스가 복잡해 질수록 유지 보수가 어려워지는 원인이 됩니다.

Serializable이 시스템 비용이 발생한다면 Parcelable 은 구현 과 유지, 보수에 드는 사용자의 노력을 비용으로 지불해야 합니다.

Parcelable VS Serializable

인터넷에서는 Parcelable 과 Serializable 을 비교하는 많은 정보를 찾을수 있습니다.

인터넷에서 쉽게 접할수 있는 접근법 말고 여기에 또다른 접근방식에 대해 적어보려 합니다. 그리고 그 결과에 대한 판단은 여러분의 몫입니다.

첫 번째 그룹은 Parcelable 이 Serializable 보다 훨씬 빠르고 좋다고 주장합니다. 물론, 이 주장을 뒷받침 하는 데이터가 있습니다.

Philipe Breault의 실험 결과는 Parcelable 이 Serializable 보다 10배 이상 빠르다는 것을 보여줍니다. 일부의 구글 엔지니어들도 이 결과에 대해 지지하고 있습니다.

이 글의 가장 하단 ‘참고’ 섹션에서 Philipe Breault 의 포스트에 대한 링크를 첨부해 두었습니다.

두번째 그룹은 이 테스트는 틀린것이며, 우리 모두가 잘못 알고 있다고 주장합니다. 그리고 이 주장은 충분히 신빙성이 있어보입니다.

‘기본 사용법에 의한 Serializable’ 은 Parcelable 보다 느립니다. 이에 대한 두 그룹의 의견에는 이견이 없습니다.

하지만, Philipe Breault 의 테스트 방법은 불공평 하다고 주장합니다.

Parcelable 은 위에서 설명한 바와 같이 하나의 클래스 객체 만을 위한 특별한 사용자 정의 코드를 작성 해야만 합니다. 사용자 정의 코드의 도움으로 Parcelable 은 Serializable 과는 달리 쓰레기를 생성할 이유가 없고 그 결과 성능이 더 좋습니다.

그러나 ‘기본 사용법에 의한 Serializable’ 은 Java 의 자동 직렬화 프로세스를 사용합니다. 이 과정은 분명 Parcelable 과 같은 수고로움은 없지만 처리 과정에서 많은 쓰레기를 만들어냅니다. 따라서, 더 나쁜 결과가 나타납니다.

이제 다른 방법으로 Serializable 을 사용해 봅시다.

Serializable 에서 자동으로 처리되는 직렬화 프로세스 는 사용자가 구현한 writeObject() 와 readObject() 메서드로 대체될 수 있습니다. 사용자가 구현한 직렬화 메서드 와 함께 Serializable 접근 방식을 사용하려면 다음의 메서드 들을 반드시 구현해야 합니다.

 

마치 Parcelable 의 사용법 처럼 Serializable 의 writeObject() 와 readObject() 메서드에는 해당 클래스에 맞는 처리 로직을 포함시킬 수 있습니다. 제대로 수행 된다면, 기본 사용법에 의한 Serializable 방식 에서 발생하는 쓰레기가 더이상 생성되지 않습니다.

이제 Parcelable 과 Serializable 의 비교가 공정해 졌습니다. 테스트 결과는 놀랍습니다. 특정 클래스 처리 로직을 구현한 Serializable 은 Parcelable 보다 쓰기 속도가 3배 이상, 읽기의 경우 1.6배 더 빠릅니다.

결론

많은 문서에서 Parcelable 은 Serializable 보다 느리다고 합니다. 하지만 두번째 그룹의 테스트는 Serializable 을 Parcelable 과 같은 방식으로 구현하고 테스트 해보면 그렇지 않다는것을 알수 있습니다.

여러분의 생각은 어떤가요? 무엇에 중점을 두시겠습니까?

사용의 편리함 인가요? 아니면 속도 인가요? 속도의 빠름 이라면 Parcelable 대신 특정 클래스 처리 로직을 구현한 Serializable 을 사용 하시겠습니까? 아니면 계속 Parcelable 을 사용 하시겠습니까?

제 개인적 생각에는 0.000042 밀리초 빠르게 앱을 실행하는것에 집중하기 보다는 차라리 내가 만드는 이 앱 이 사용자가 원하는 일을 잘 처리하고 만족할 만한 결과를 내도록 집중하는것이 더 가치가 있는 일이 아닐까 싶습니다.

 


참고자료

https://medium.com/@limgyumin/parcelable-vs-serializable-%EC%A0%95%EB%A7%90-serializable%EC%9D%80-%EB%8A%90%EB%A6%B4%EA%B9%8C-bc2b9a7ba810

 

Parcelable vs Serializable , 정말 Serializable은 느릴까?

원문 : “Parcelable vs Serializable”

medium.com

https://best-human-developer.tistory.com/133

 

[Android] Serializable vs Parcelable

익숙한 Serializable과 Parcelable Serializable과 Parcelable, 익숙한 녀석들이다. Bundle에 객체를 담아 Intent와 arguments를 통해 다른 곳으로 전달하려면 객체의 클래스가 둘 중 하나를 구현(상속)해야 한다. 나

best-human-developer.tistory.com

https://work2type.tistory.com/entry/Serializable-Parcelable-%EC%B0%A8%EC%9D%B4

 

Serializable Parcelable 차이

안드로이드에는 Activity, Service, Broadcast Receiver, Contents Provider라는 4대 컴포넌트라는 것이 존재한다. 서로 알아서 소통하면 얼마나 좋을까? 하지만 그렇지 않기 때문에 개발자가 오작교를 놔줘야한

work2type.tistory.com

 

'Android' 카테고리의 다른 글

[Android] MQTT 통신  (0) 2023.09.11