(Android/안드로이드) BadParcelableException() 해결 방법

개요


1. 왜 Parcelable 대신 JSON String이 해결책이 되나?

즉, “Parcelable이 깨질 수 있는 환경”에서 String 기반 전달은 구조적으로 더 튼튼한 우회로가 됩니다.


2. 구현: Gson으로 직렬화해서 putExtra로 넘기기

2.1 데이터 모델

data class People(
    val id: Int,
    val name: String
)

2.2 보내는 쪽: 객체 → JSON String

private const val EXTRA_PEOPLE_JSON = "extra_people_json"

fun Context.openDetail(people: People) {
    val gson = Gson()
    val json = gson.toJson(people)

    val intent = Intent(this, DetailActivity::class.java).apply {
        putExtra(EXTRA_PEOPLE_JSON, json)
    }
    startActivity(intent)
}

2.3 받는 쪽: JSON String -> 객체

class DetailActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val json = intent.getStringExtra(EXTRA_PEOPLE_JSON)
        require(!json.isNullOrBlank()) { "people json is null/blank" }

        val people = Gson().fromJson(json, People::class.java)

        // use people...
    }
}

3. 리스트/제네릭 타입까지 다룰 때 (TypeToken)

val type = object : TypeToken<List<People>>() {}.type
val peopleList: List<People> = Gson().fromJson(json, type)

4. 실무에서 꼭 넣는 안전장치 3가지

4.1 JSON 버전 필드 넣기 (권장)

// 모델이 바뀌면 old JSON이 파싱 실패할 수 있어 “버전”을 넣으면 안정적입니다.
data class PeoplePayload(
    val version: Int = 1,
    val data: People
)

4.2 파싱 실패 대비 runCatching

val people = runCatching {
    Gson().fromJson(json, People::class.java)
}.getOrNull()

4.3 큰 데이터는 여전히 금지


5. Parcelable vs Gson String

항목 Parcelable Gson JSON String
classLoader 의존 큼(복원 시 필요) 거의 없음
성능 빠름 파싱 비용 있음
안정성(복원/모듈) 환경에 따라 깨짐 상대적으로 안정
타입 안정성 강함 런타임 파싱
대용량 전송 위험 똑같이 위험


Related Posts