직렬화

Pardess·2025년 4월 24일

직렬화

객체를 저장하거나 전송하기 위해 byte stream 형태로 변환하는 작업

Java Serializable

내부적으로 Reflection 기반 → 느리고 메모리 낭비가 심함.

리플랙션

면접 답변 예시 (기본 + 실무 관점)

리플렉션(Reflection)은 런타임 시점에 클래스, 메서드, 필드 등의 정보를 확인하고 코드의 이름을 문자열로 동적 접근하거나 실행할 수 있게 해주는 기능입니다.

컴파일 타임이 아닌 런타임에 구조를 분석할 수 있기 때문에 런타임에 타입 오류가 발생하거나, 성능 저하가 바생합니다.

  • 성능 저하
    • 리플렉션은 내부적으로 메타데이터를 분석하는 작업이 포함되기 때문에
    일반 메서드 호출보다 **훨씬 느립니다.**
    
  • 안정성 부족
    • 컴파일 타임에 오류를 잡지 못하고, 런타임에 예외가 발생할 수 있어 디버깅이 어렵습니다.
  • Proguard와 충돌
    • 클래스/메서드 이름이 변경되면 리플렉션이 실패할 수 있어서, Proguard 예외 설정을 잘 관리해야 합니다.
  • 접근 제어 무시
    • private 필드도 강제로 접근 가능 → 보안상 위험

요약 답변

정리하면, 리플렉션은 런타임에 클래스나 객체 정보를 분석하고 동적으로 메서드를 호출하거나 필드에 접근할 수 있는 기능입니다.

매우 유용하지만, 성능 저하와 예외 발생 가능성 때문에 안드로이드에서는 주로 대체 기술(KAPT, KSP, Codegen 등) 을 활용하여 리플렉션 없이 유사한 결과를 얻는 방향으로 발전하고 있습니다.

Android Parcelable

Android에서 사용하는 고성능 객체 직렬화 방식
Parcel 객체를 통해 데이터를 직접 쓴다

장점

  • 빠름 (Reflection 없이 직접 메모리 복사)
  • Intent, Bundle에 최적화
  • 데이터를 메모리 블록에 연속적으로 저장합니다.

면접형 답변 예시

Parcelable은 안드로이드에서 객체를 직렬화하는 전용 방식으로,

내부적으로는 Parcel이라는 컨테이너에 객체의 필드들을 순차적으로 직접 write/read 하면서 바이너리 형태로 변환합니다.

이 과정은 Reflection을 사용하지 않고, 메모리 복사 수준의 빠른 처리를 하기 때문에

Serializable보다 훨씬 빠르고 메모리 효율이 좋습니다.

그래서 Intent, Bundle, AIDL 등 IPC에서 최적화된 포맷으로 사용됩니다.

정리 (면접용 마무리 요약)

Parcelable은 안드로이드 시스템 전용 직렬화 방식으로, Parcel이라는 메모리 버퍼에 객체의 필드를 직접 쓰고 읽는 구조입니다.

리플렉션 없이 작동하기 때문에 Serializable보다 빠르고 가볍고,

Intent, Bundle, AIDL과 같은 Android IPC에서 가장 적합한 방식입니다

정리

네, 리플렉션은 변수, 클래스, 메서드의 이름(문자열) 을 메타데이터로 삼아 동적으로 접근합니다.

그래서 이름이 바뀌거나 난독화되면 오작동 위험이 있고, 타입 안정성이 떨어지기 때문에

Android에서는 되도록 컴파일 타임에 처리하는 방식(Codegen) 을 선호합니다.

Json 직렬화(Gson / Moshi / kotlinx.serialization)

  • 서버 통신, 파일 저장 등에 가장 많이 사용됨
  • 객체 ↔ JSON 문자열 변환

장점

  • 직관적이고 범용적
  • 서버-클라이언트 통신에 최적
  • 저장, 디버깅, 로그 등에도 유용

단점

  • 퍼포먼스: Parcel보다 느림
  • 타입 안정성 부족 (런타임 오류 가능)

Gson (Google)

  • 가장 오래된 JSON 파서
  • 사용 간단하고 학습 자료 많음
  • Android SDK에 거의 기본처럼 사용됨

장점

  • 코드가 매우 간단
  • 동적 JSON 처리에 강함 (ex. JsonObject, JsonArray)
  • 커스터마이징이 매우 자유로움 (TypeAdapter, ExclusionStrategy 등)

단점

  • 리플렉션 사용 → 성능 저하
  • Kotlin 지원이 부족 (null, default 값 이슈)
  • Proguard 설정 복잡

kotlinx.serialization (JetBrains)

📌 특징

  • Kotlin 공식 직렬화 라이브러리
  • Multiplatform 지원 (Kotlin/JS, Kotlin/Native, Kotlin/Android 등)
  • 컴파일 타임에 코드 생성 → 가장 빠름 + 타입 안전성 최고

장점

  • 가장 Kotlin스럽고 빠름
  • Flow, Coroutine, DataStore, Ktor 등과 연동 쉬움
  • Multiplatform 지원 (KMP 최적화)
  • 런타임 에러 줄이고 타입 안전성 확보

단점

  • 동적 JSON 구조 처리 어려움 (JsonObject 조작 불편)
  • 고급 커스터마이징은 제한적 (디코더 커스터마이징 어려움)

Protocol Buffer

  • 고성능 바이너리 직렬화 포맷
  • DataStore에서 ProtoDataStore로 사용됨

장점

  • 매우 작고 빠름
  • 정적 타입, 구조화, 오류에 강함
  • 서버 ↔ 클라이언트 간 통신 + 로컬 저장에 적합

단점

  • .proto 파일 필요
  • 가독성이 낮음 (바이너리 포맷)

Codegen(코드 생성)

컴파일 타임이나 빌드 타임에 자동으로 Kotlin 소스 코드를 생성하는 기술입니다.

대표적으로 DI(Hilt), 직렬화(Moshi, kotlinx.serialization), DB(Room), ViewBinding 등에서 쓰입니다.

리플렉션Codegen
런타임에 객체 구조 파악 (느림, 불안정)컴파일 타임에 필요한 코드를 자동 생성 (빠름, 안전)
동작은 유연하지만 느리고 예외 위험성능 좋고, 컴파일 시 에러 감지 가능
Proguard 이슈 발생 가능Proguard 문제 거의 없음

장점 요약

  • 런타임 리플렉션 제거 → 성능 향상
  • 컴파일 시 타입 체크 → 안정성 증가
  • 자동 생성으로 반복 코딩 감소
  • Proguard 이슈 거의 없음

단점 / 주의점

  • 빌드 시간이 늘어날 수 있음 (특히 KAPT 기반은 무겁고 느림)
  • 빌드 실패 시 디버깅 어려움 (코드가 눈에 보이지 않음)
  • 멀티모듈 프로젝트에서 의존성 주의 필요

마무리 요약 (면접형)

Codegen은 컴파일 타임에 반복적이거나 구조적인 코드를 자동으로 생성해주는 방식입니다.

안드로이드에서는 DI(Hilt), 직렬화(Moshi, kotlinx.serialization), 데이터베이스(Room) 등에서

리플렉션을 대체하여 성능과 안정성을 확보하기 위해 널리 사용되고 있습니다.

최근에는 KAPT보다 더 빠르고 Kotlin 친화적인 KSP 기반 Codegen이 많이 도입되고 있습니다.

0개의 댓글