Serializable vs Parcelable 차이점 알아보기

aufcl4858·2025년 8월 10일
post-thumbnail

안드로이드 개발을 하다 보면 Activity 간에 데이터를 전달하거나 객체를 저장해야 할 때가 많다. 이때 마주치는 것이 바로 SerializableParcelable이다. 둘 다 객체를 직렬화하는 방법이지만, 성능과 사용법에서 큰 차이가 있다.

직렬화와 바이트 스트림

직렬화란 메모리에 있는 객체를 저장이나 전송이 가능한 바이트 스트림으로 변환하는 과정이다. 바이트 스트림은 데이터를 8비트 단위로 연속적으로 처리하는 데이터 흐름으로, 모든 컴퓨터가 이해할 수 있는 가장 기본적인 형태다.

// 메모리의 객체 (전송 불가능)
val user = User("김철수", 30)

// ↓ 직렬화 (마샬링)
// 바이트 스트림 (전송 가능)
[01001000][01100101][01101100][01101100][01101111]...

// ↓ 역직렬화 (언마샬링)  
// 다시 객체로 복원

직렬화를 마샬링(Marshalling), 역직렬화를 언마샬링(Unmarshalling)이라고도 부르는데, 주로 네트워크나 IPC 통신에서 이 용어들을 많이 사용한다.

Serializable - 편리하지만 느린 Java 표준

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

// 사용법 - 매우 간단!
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)

Serializable은 런타임에 리플렉션을 사용해서 동작한다. 리플렉션이란 프로그램이 실행 중에 자기 자신의 구조(클래스, 메서드, 필드 등)를 검사하고 조작할 수 있는 기능이다. 마치 의사가 환자를 진료할 때 "어디가 아픈지 모르니까 일단 전체적으로 검사해보자"는 식으로 동작한다.

장점:

  • 구현이 매우 간단 (인터페이스만 구현하면 끝)
  • Java 표준이라 어디서나 사용 가능

단점:

  • 리플렉션으로 인한 성능 저하 (필드 검색, 타입 체크, 보안 검사 등)
  • 박싱/언박싱으로 인한 대량의 임시 객체 생성
  • 메타데이터 오버헤드로 용량 비효율

Parcelable - 안드로이드 최적화

@Parcelize
data class User(
    val name: String,
    val age: Int
) : Parcelable

// 사용법 - Serializable과 동일!
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)

Parcelable은 컴파일 타임에 미리 최적화된 코드를 생성한다. 리플렉션 없이 직접 메모리에 접근하므로 훨씬 빠르다.

여기서 Parcelable(인터페이스)Parcel(실제 컨테이너)의 관계를 이해하는 것이 중요하다. Parcelable은 "포장 방법을 아는 물건"이고, Parcel은 "실제 포장하는 상자"라고 생각하면 된다. Parcelable 객체가 Parcel이라는 도구를 사용해서 자신을 직렬화하는 구조다.

장점:

  • 매우 빠른 성능 (리플렉션 없음, 직접 메모리 접근)
  • 메모리 효율적 (임시 객체 최소화)
  • IPC(Inter-Process Communication) 최적화
  • @Parcelize로 간단한 구현

단점:

  • 안드로이드 전용

Parcelable은 특히 안드로이드의 IPC(프로세스 간 통신)에 최적화되어 있다. intent.putExtra()를 사용할 때 기본 타입, Parcelable, Serializable만 전달할 수 있는 이유가 바로 여기에 있다. 이들은 "프로세스 간 안전하게 직렬화될 수 있는 타입들"이기 때문이다.

실제 직렬화는 putExtra 호출 시점이 아니라 startActivity() 같은 IPC 통신이 일어날 때 발생한다. Android의 Binder 시스템을 통해 Activity 간, 혹은 앱과 시스템 서비스 간 데이터를 전달할 때 Parcelable의 효율성이 빛을 발한다.

실제 성능 차이

같은 User 객체를 저장할 때:

  • Serializable: ~200바이트 (메타데이터 70% + 실제 데이터 30%)
  • Parcelable: ~18바이트 (거의 순수 데이터만)

성능 테스트 결과:

// 1000개 객체 직렬화
// Serializable: 1000ms, 메모리 50MB
// Parcelable:   50ms,   메모리 5MB

20배의 성능 차이가 난다!

JSON vs 직렬화: 언제 뭘 써야 할까?

안드로이드 내부 통신 → Parcelable

  • Activity/Fragment 간 데이터 전달
  • Bundle에 객체 저장
  • 화면 회전 시 상태 보존

서버 통신 → JSON

  • REST API 호출
  • 웹소켓 통신
  • 다른 플랫폼과의 데이터 교환

로컬 저장 → 상황에 따라

  • 성능 중요: Parcelable
  • 가독성/디버깅 중요: JSON
  • 단순함 우선: Serializable

마무리

Parcelable은 Serializable의 비효율성을 해결하기 위해 만들어진 안드로이드 전용 솔루션이다. 컴파일 타임 vs 런타임, 직접 접근 vs 리플렉션의 차이가 엄청난 성능 격차를 만들어낸다.

안드로이드 개발에서는 성능상의 이유로 Parcelable 사용을 강력히 권장한다. @Parcelize 어노테이션 덕분에 구현도 간단해졌으니, 이제 Serializable을 쓸 이유가 거의 없다고 봐도 무방하다.

성능에 민감한 모바일 환경에서는 작은 차이도 사용자 경험에 큰 영향을 미친다. 올바른 직렬화 방식 선택으로 더 나은 앱을 만들어보자.

profile
데브누누

0개의 댓글