Parcelable vs Serializable

종종 앱을 개발하다보면 액티비티와 같은 안드로이드 컴포넌트에 POJO같은 데이터를 전달해야 할 일이 있습니다. 액티비티 객체는 우리가 만들지 않고 안드로이드 시스템에서 관리하고 있으므로 컴포넌트로 데이터를 전달하기 위해서는 반드시 인텐트를 통해서 전달하게 됩니다.

Serializable

Serial(직렬의) + ~able(~가능한)
Serializable(시리어라이저블)은 자바 표준 인터페이스 중 하나로 안드로이드 SDK에 포함되어있지 않습니다. 어쨌거나 전달하고자 하는 데이터 클래스(POJO)에 Serializable인터페이스를 구현만 하면 액티비티로 데이터를 전달할 준비가 완료 됩니다. 예제를 한번 보시죠.

import java.io.Serializable;

public class Person implements Serializable {

    private String name;
    private int age;


    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

아주 간단하게 implements Serializable 을 추가 하는것으로 Person객체를 다른 액티비티에 전달할 준비가 완료 되었습니다.

간단하게 구현만큼 그에 따른 댓가를 치르게 됩니다. 내부적으로는 자바의 리플렉션의 발생하게 되고 이로 인해 많은 오브젝트 생성과 그에 따른 Garbage Collection이 발생하게 되어 안드로이드 앱의 성능을 낮추고 베터리를 더 잡아 먹게 됩니다.

Parcelable

Parcel(소포, 택배) + ~able(~가능한)
Parcelable(파슬러블)은 또 다른 인터페이스의 한종류로 자바가 아닌 안드로이드 SDK내에 포함되어있습니다. Parcelable은 리플렉션을 사용하지 않기위해 특별하게 설계되었습니다. 우선 예제를 한번 확인해보도록하겠습니다.

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable {

    private String name;
    private int age;


    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.age);
    }

    protected Person(Parcel in) {
        this.name = in.readString();
        this.age = in.readInt();
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel source) {
            return new Person(source);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

리플렉션을 없애기 위해 유지보수가 힘든 보일러플레이트 코드가 생겼지만 퍼포먼스는 향상됩니다.

옛날 기기 대상 지표긴 하지만 여전히 비슷하게 적용됩니다. 압도적으로 Parcelable인터페이스가 데이터를 전달할때 적은 시간을 소요하는것을 확인할 수 있습니다.

Why is it so FAST?

두 방식 모두 프로세스들 사이에서 통신(IPC)하는 방식이지만, Serialzable은 JVM상에서 리플렉션API를 사용합니다 이는 자바 객체 멤버 및 동작을 식별하지만 불필요한 객체(Garbage objects)도 많이 생성하게 되는데, 이로 인해 Serialzable을 사용하는 처리는 Parcelable과 비교해서 느립니다.

Serializable 방식에서 자동으로 처리되는 직렬화 프로세스도 Parcelable처럼 writeObject()와  readObject()를 구현하면 Parcelable보다 더 빠르다는 의견과 테스트 내용도 있으니 참고하시면 좋을 것 같습니다.

Parcelable vs Serializable 정말 Serializable은 느릴까?

Note : 안드로이드 스튜디오(InjelliJ IDE)의 플러그인을 활용하면 쉽게 보일러플레이트 코드를 생성할 수 있습니다. 코틀린에서는 @Parcelize를 사용하면 더욱 쉽게 Parcelable을 구현할 수 있습니다.

Conclusion

Serializable은 분명히 개발자 입장에서는 편합니다. 인터페이스 구현만 하면되니까요. 하지만 앱 사용자에게는 퍼포먼스저하와 베터리 드래인이라는 큰 단점을 안겨 줍니다. 조금은 귀찮더라도 Serializable은 지양하고 Parcelable을 사용하는 것이 바람직 합니다.

 

카테고리: Java

5개의 댓글

chu · 2020년 3월 26일 3:38 오후

예) putExtra(Parcelable) 또는 putExtra(Parcelable) << 같은 아이 두번 연속인데 "또는" 이 들어갔어요!ㅎㅎ

    Charlezz · 2020년 3월 27일 4:25 오후

    수정했습니다 🙂

성빈 · 2022년 5월 30일 9:46 오전

깔끔한 정리 감사합니다 🙂

질문 · 2022년 12월 17일 11:35 오후

serialization도 IPC를 쓰지 않나요? 갑자기 결말이 이상한데..

    Charlezz · 2022년 12월 28일 5:27 오후

    Serializable도 IPC입니다. 덕분에 부족한 부분을 수정했습니다. 의견 감사합니다!

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.