본문 바로가기

안드로이드

Android에서의 객체 전달 방법 비교 Serializable vs Parcelable, Parcel

반응형

안드로이드 개발을 하다 보면 액티비티(Activity) 간, 혹은 서비스(Service) 간 데이터를 전송해야 하는 경우가 많습니다. 이때 자주 사용되는 방법이 SerializableParcelable이며, 실제 데이터를 담아 전달하는 그릇 역할로 Parcel이 사용됩니다. 이번 포스팅에서는 각각이 무엇이며 왜 쓰이는지, 어떤 상황에서 더 유용한지, 간단 예제까지 살펴보겠습니다.


1. Serializable

1.1 특징

  • Java 표준 인터페이스: java.io.Serializable 인터페이스를 구현하기만 하면 됩니다.
  • Reflection 기반: 런타임에 리플렉션을 통해 필드를 직렬화하기 때문에 단순 구현이 가능하지만, 그만큼 속도가 느리고 오버헤드가 큼.
  • 사용 용도: 안드로이드가 아닌 순수 Java 환경에서도 사용 가능. 안드로이드에서 간단한 객체 전달에 사용할 수 있으나, 성능이 크게 중요하지 않을 때 추천됩니다.

1.2 장단점

  • 장점:
    • 손쉽게 구현 가능
    • Java 표준이므로 범용적
  • 단점:
    • 상대적으로 느린 직렬화
    • 오버헤드가 큼(가비지 객체 생성 많음)

1.3 간단 예제 (Kotlin)

// 직렬화할 클래스
import java.io.Serializable

data class MySerializableData(
    val name: String,
    val age: Int
) : Serializable

// 사용 예시 (Activity 간 전달)
// 첫 번째 Activity
val intent = Intent(this, SecondActivity::class.java).apply {
    putExtra("myData", MySerializableData("Alice", 20))
}
startActivity(intent)

// 두 번째 Activity에서 받는 법
val myData = intent.getSerializableExtra("myData") as? MySerializableData
myData?.let {
    Log.d("SecondActivity", "이름: ${it.name}, 나이: ${it.age}")
}

2. Parcelable

2.1 특징

  • 안드로이드 전용 인터페이스: android.os.Parcelable 인터페이스를 구현해야 합니다.
  • 성능 최적화: 내부적으로 리플렉션을 사용하지 않고, 직접 읽고 쓰는 방식을 제공해 빠른 직렬화가 가능합니다.
  • 사용 용도: 안드로이드 환경에서 액티비티 간 데이터 전달이나 IPC(Inter-Process Communication) 상황에서 자주 사용. 성능이 중요한 경우 Parcelable을 권장합니다.

2.2 장단점

  • 장점:
    • 빠른 직렬화 및 역직렬화
    • 가비지 객체 생성이 적어 메모리 효율적
  • 단점:
    • 구현이 다소 번거로움(생성자, writeToParcel, CREATOR 등)

2.3 간단 예제 (Kotlin)

// 직렬화할 클래스
import android.os.Parcel
import android.os.Parcelable

data class MyParcelableData(
    val name: String,
    val age: Int
) : Parcelable {

    // Parcel에서 읽어들이는 생성자
    constructor(parcel: Parcel) : this(
        parcel.readString().toString(),
        parcel.readInt()
    )

    // 객체 직렬화
    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeInt(age)
    }

    // 보통 0 리턴
    override fun describeContents(): Int = 0

    companion object CREATOR : Parcelable.Creator<MyParcelableData> {
        override fun createFromParcel(parcel: Parcel): MyParcelableData {
            return MyParcelableData(parcel)
        }

        override fun newArray(size: Int): Array<MyParcelableData?> {
            return arrayOfNulls(size)
        }
    }
}

// 사용 예시 (Activity 간 전달)
// 첫 번째 Activity
val intent = Intent(this, SecondActivity::class.java).apply {
    putExtra("myData", MyParcelableData("Bob", 25))
}
startActivity(intent)

// 두 번째 Activity에서 받는 법
val myData = intent.getParcelableExtra<MyParcelableData>("myData")
myData?.let {
    Log.d("SecondActivity", "이름: ${it.name}, 나이: ${it.age}")
}

3. Parcel

3.1 Parcel이란?

  • 안드로이드에서 IPC를 위한 데이터를 담는 컨테이너 클래스입니다.
  • 안드로이드 내부에서 객체를 다른 컴포넌트로 전달할 때, 객체를 flatten(직렬화) 하고 다시 unflatten(역직렬화) 하는 과정을 수행합니다.
  • Parcel 자체는 일반적인 직렬화 용도로 쓰면 안 되며, 파일로 저장하거나 네트워크 전송 용도로 적합하지 않습니다. (안드로이드 버전에 따라 Parcel 구조가 달라질 수 있음)

3.2 Parcel과 Parcelable의 관계

  • Parcelable을 구현한 객체는 Parcel을 통해 직렬화/역직렬화됩니다.
  • Parcel은 기본 자료형(문자열, 정수 등)부터 배열, Parcelable 객체 등을 효율적으로 쓰고 읽을 수 있도록 메서드를 제공합니다.

4. Serializable vs. Parcelable 비교 표

구분SerializableParcelable

타입 Java 표준 인터페이스 안드로이드 전용 인터페이스
성능 느림(리플렉션 사용) 빠름(리플렉션 미사용, 직접 처리)
가비지 생성 많음 적음
사용 편의 구현 간단 구현 복잡
주 사용 용도 안드로이드 외도 가능 안드로이드 내에서 주로 사용

5. 어떤 것을 선택해야 할까?

  1. 성능이 중요한 경우: Parcelable을 권장합니다. 예를 들어 큰 데이터를 자주 주고받거나, IPC가 빈번하게 발생하는 경우, Parcelable로 작성된 객체가 훨씬 빠르게 직렬화/역직렬화됩니다.
  2. 간단하고 범용적인 코드가 필요한 경우: 안드로이드 밖의 Java 환경과도 호환하려면 Serializable을 사용할 수 있습니다. 구현이 간단하므로 성능 요구 사항이 낮은 경우에 괜찮습니다.
  3. 규모가 큰 앱: 대규모 앱일수록 Parcelable를 사용해 불필요한 오버헤드를 줄이는 것이 좋습니다.
  4. 간단한 테스트프로토타입: 개발 단계에서 빠르게 구조를 잡고 테스트하려면 Serializable도 나쁘지 않습니다. 추후에 필요에 따라 Parcelable로 변환할 수 있습니다.

6. 결론

  • Serializable:
    • 장점: 간단, Java 표준, 안드로이드 외에서도 사용 가능
    • 단점: 느리고 오버헤드가 많음
    • 추천 상황: 데이터가 적고, 성능에 크게 구애받지 않을 때, 또는 안드로이드 외 코드와 공유가 필요할 때
  • Parcelable:
    • 장점: 빠른 직렬화, 가비지 최소화
    • 단점: 구현 복잡
    • 추천 상황: 안드로이드 환경에서 자주 데이터를 전달하거나 성능이 중요할 때
  • Parcel:
    • 안드로이드 IPC를 위한 핵심 클래스
    • 직접 사용하는 경우는 상대적으로 적지만, Parcelable을 구현할 때 내부적으로 Parcel을 이용해 데이터를 쓰고 읽습니다.
    • 일반 저장 용도(예: 파일)로 사용해서는 안 됩니다.

안드로이드 개발을 진행하다 보면 많은 경우에 Parcelable이 권장되지만, 상황에 따라 Serializable을 택해야 하는 때도 있을 것입니다. 각 방식의 장단점을 잘 파악하고, 어플리케이션의 성능 요구사항개발 편의성을 모두 고려해 선택하는 것이 좋겠습니다.


참고

반응형