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

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

Serializable 이란 무엇인가?

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

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

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

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

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

Parcelable 은 무엇인가?

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

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

다음의 코드 에서 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 밀리초 빠르게 앱을 실행하는것에 집중하기 보다는 차라리 내가 만드는 이 앱 이 사용자가 원하는 일을 잘 처리하고 만족할 만한 결과를 내도록 집중하는것이 더 가치가 있는 일이 아닐까 싶습니다.

참고