모바일 개발에서 데이터 직렬화: 본질, 형식 및 작동 방식

저자: IT Sectr 게시일: 2026-03-15 읽는 시간: 8 분

직렬화와 역직렬화는 객체를 전송 또는 저장을 위한 형식으로 변환하는 기본적인 프로세스입니다. 모바일 개발에서 이러한 메커니즘은 모든 네트워크 요청, 상태 저장 및 프로세스 간 통신에서 사용됩니다. MDN Web Docs, 2024에 따르면, JSON은 웹 및 모바일 애플리케이션에서 가장 인기 있는 직렬화 형식으로 XML과 Protocol Buffers를 능가하고 있습니다.

주요 내용

  • 직렬화 — 전송 또는 저장을 위해 객체를 바이트 시퀀스로 변환
  • 역직렬화 — 바이트 표현에서 객체를 복원하는 역과정
  • JSON — 사람이 읽을 수 있고 모든 플랫폼에서 지원되는 텍스트 형식
  • Protocol Buffers — 높은 속도와 컴팩트한 크기의 Google 바이너리 형식
  • XML — 검증 스키마 및 네임스페이스 지원이 있는 확장 가능한 마크업 언어

직렬화와 역직렬화의 본질

직렬화는 애플리케이션 객체를 네트워크 전송 또는 디스크 저장에 적합한 형식으로 변환하는 프로세스입니다. 역직렬화는 수신된 데이터에서 객체를 복원하는 역변환을 수행합니다. 모바일 개발에서 직렬화는 API 요청, 화면 상태 저장, 캐싱 및 Intent 또는 Bundle을 통한 데이터 전송에 사용됩니다.

필요성이 발생하는 경우

애플리케이션 구성 요소 간 또는 애플리케이션과 서버 간의 모든 상호 작용에는 직렬화가 필요합니다. REST API는 JSON 또는 XML로 데이터를 전송하고, gRPC는 Protocol Buffers를 사용하며, Android의 프로세스 내 통신은 Parcelable을 사용합니다. 직렬화 없이는 프로세스 경계를 넘어 복잡한 객체를 전달하거나 데이터베이스에 저장하는 것이 불가능합니다.

kotlin
// 직렬화의 일반 원칙
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// 직렬화: 객체 -> JSON
fun serializeUser(user: User): String {
    return """{"id":${user.id},"name":"${user.name}","email":"${user.email}"}"""
}

// 역직렬화: JSON -> 객체
fun deserializeUser(json: String): User? {
    // JSON을 객체로 파싱
    return Gson().fromJson(json, User::class.java)
}
형식크기속도가독성타이핑
JSON중간높음높음동적
XML중간높음XSD 스키마
Protocol Buffers작음매우 높음낮음엄격한 .proto
FlatBuffers작음최대낮음엄격한 .fbs

JSON — 모바일 개발의 주요 형식

JSON(JavaScript Object Notation)은 JavaScript 객체 구문을 기반으로 하는 경량 텍스트 형식입니다. JSON은 문자열, 숫자, 부울 값, 배열 및 중첩 객체를 지원하여 모바일 애플리케이션의 대부분의 데이터 전송 시나리오를 포괄합니다. 이 형식은 플랫폼에 독립적입니다. 각 생태계는 구문 분석을 위한 내장 도구를 제공합니다.

대안에 비해 JSON의 장점

JSON은 단순성과 다용성으로 인해 우수합니다. 개발자는 기본 사용을 위해 스키마가 필요하지 않습니다. 구조는 구문 분석 중에 동적으로 결정됩니다. 형식의 가독성은 디버깅과 테스트를 단순화합니다. 서버 응답은 모든 개발자 도구에서 볼 수 있습니다. 두 모바일 플랫폼 모두에서 JSON은 타사 라이브러리 없이 기본적으로 처리됩니다.

swift
// Codable — Swift의 네이티브 JSON 직렬화
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

let jsonString = """{"id":1,"name":"John","email":"john@test.com"}"""
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
let user = try! decoder.decode(User.self, from: jsonData)

Google의 Protocol Buffers

Protocol Buffers(protobuf)는 고성능 시스템을 위해 Google이 개발한 바이너리 직렬화 형식입니다. JSON과 달리 protobuf는 .proto 파일에 미리 정의된 스키마가 필요하지만 훨씬 작은 데이터 크기와 더 높은 처리 속도를 제공합니다. 이 형식은 gRPC, Firebase Firestore 및 Google 내부 서비스에서 사용됩니다.

.proto 파일의 구조

protobuf 스키마는 각각 고유 번호가 있는 유형화된 필드를 가진 메시지를 설명합니다. protoc 컴파일러는 직렬화와 역직렬화를 자동으로 수행하는 대상 언어의 클래스를 생성합니다. Protobuf는 하위 호환성을 잃지 않고 필드를 추가 및 제거하는 규칙을 통해 스키마 발전을 지원합니다.

cpp
// user.proto의 스키마 정의
syntax = "proto3";

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  repeated string roles = 4;
}

// Kotlin으로 생성된 코드
val user = UserProto.User.newBuilder()
    .setId(1)
    .setName("John")
    .setEmail("john@test.com")
    .build()

val bytes: ByteArray = user.toByteArray()

XML과 그 응용

XML(eXtensible Markup Language)은 엄격한 구조, 네임스페이스 지원 및 XSD 스키마를 통한 검증을 제공하는 형식입니다. XML은 컴팩트함과 구문 분석 속도에서 JSON에 뒤지지만 Android 개발에서 레이아웃 파일, AndroidManifest, 리소스 및 Gradle 구성에 대한 수요가 있습니다. iOS에서는 XML이 plist 파일 및 일부 레거시 서비스에서 사용됩니다.

Android에서 XML 구문 분석

Android는 XML 구문 분석에 세 가지 접근 방식을 제공합니다: DOM(전체 문서를 메모리에 로드), SAX(이벤트 기반 스트리밍 구문 분석) 및 XmlPullParser(하이브리드 접근 방식)입니다. XmlPullParser는 모바일 장치에 권장되는 옵션으로, 제한된 메모리에서 효율적으로 작동하며 읽으면서 문서를 처리할 수 있습니다.

kotlin
// Android의 XmlPullParser
fun parseUserXml(inputStream: InputStream): User? {
    val parser = Xml.newPullParser()
    parser.setInput(inputStream, Xml.Encoding.UTF_8.name)

    var id: Int? = null
    var name: String? = null
    var email: String? = null

    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.eventType == XmlPullParser.START_TAG
            && parser.name == "email") {
            email = parser.nextText()
        }
    }
    return User(id!!, name!!, email!!)
}

iOS 및 Android에서의 직렬화

각 플랫폼은 자체 직렬화 도구를 제공합니다. iOS에서 기본 메커니즘은 JSONEncoder 및 JSONDecoder를 사용하는 Codable 프로토콜이고, Objective-C는 NSJSONSerialization을 사용합니다. Android는 Gson, Moshi 및 kotlinx.serialization 라이브러리를 사용합니다. 프로세스 간 데이터 전송을 위해 Android는 Parcelable을 사용하고 iOS는 NSKeyedArchiver를 사용합니다. Kotlin 프로젝트는 점점 더 kotlinx.serialization을 선택하고 있습니다. 이는 JetBrains의 솔루션으로 멀티플랫폼을 지원하고 리플렉션에 의존하지 않으며 Kotlin 컴파일러 플러그인을 통해 컴파일 타임에 직렬화기를 생성합니다.

Android에서 Parcelable vs Serializable

Android는 Intent 및 Bundle에 대해 두 가지 직렬화 메커니즘을 지원합니다. Serializable은 리플렉션을 사용하는 표준 Java 메커니즘으로 성능이 낮습니다. Parcelable은 Android 특화 프로토콜로 writeToParcel 및 createFromParcel 메서드의 수동 구현이 필요하지만 직접 바이트 조작으로 인해 수십 배 더 빠르게 작동합니다.

kotlin
// Android의 Parcelable
@Parcelize
data class UserParcel(
    val id: Int,
    val name: String,
    val email: String
) : Parcelable

// Intent를 통한 전송
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", userParcel)
startActivity(intent)

iOS에서 컨트롤러 간 데이터 전송에는 Data로의 사전 직렬화를 통한 Codable이 사용되고, 프로세스 간 통신에는 NSKeyedArchiver가 사용되어 객체를 바이너리 Property List 형식으로 변환합니다. 최신 SwiftUI 프로젝트는 애플리케이션 모듈 간 전송을 위해 JSONEncoder를 통해 데이터를 인코딩하는 것을 선호합니다.

직렬화 보안

신뢰할 수 없는 데이터의 잘못된 역직렬화는 취약점으로 이어질 수 있습니다. 직렬화 공격은 Java에서 재정의된 readObject 메서드나 타사 라이브러리의 안전하지 않은 역직렬화기를 악용합니다. Android에서는 신뢰할 수 없는 소스의 데이터에 Serializable을 피하고 대신 Parcelable 또는 역직렬화 후 모든 필드의 수동 검증을 사용해야 합니다. iOS에서 JSONDecoder는 기본적으로 타입에 대해 엄격하지만 JSONSerialization으로 작업할 때 개발자는 조건부 캐스팅을 통해 타입을 확인해야 합니다.

프로젝트를 위한 형식 선택

직렬화 형식을 선택할 때 성능 요구 사항, 데이터 크기 및 호환성이 고려됩니다. REST API 및 마이크로서비스 아키텍처의 경우 JSON이 최적의 선택으로 남아 있으며 모든 플랫폼과 언어에서 지원됩니다. 고부하 시스템 및 제한된 대역폭의 모바일 애플리케이션의 경우 더 작은 크기와 더 빠른 역직렬화를 제공하는 Protocol Buffers가 선호됩니다. XML은 구성 시나리오 및 레거시 시스템과의 통합에서만 정당화됩니다. 최신 프로젝트에서는 역직렬화 단계가 없는 바이너리 형식인 FlatBuffers의 인기도 높아지고 있으며 게임 엔진 및 지연 시간에 민감한 애플리케이션에서 사용됩니다. 각 형식에는 자체 영역이 있으며 올바른 선택은 애플리케이션 속도와 소비 트래픽 양에 직접적인 영향을 미칩니다.

자주 묻는 질문

간단히 말해 직렬화란 무엇인가요?

직렬화는 애플리케이션 객체를 네트워크를 통해 보내거나 파일에 저장할 수 있는 형식으로 패키징하는 것입니다. 물건의 사진을 찍는다고 상상해 보세요. 사진은 직렬화이고, 사진에서 물건을 복원하는 것은 역직렬화입니다.

JSON과 Protocol Buffers의 차이점은 무엇인가요?

JSON은 사람이 읽을 수 있고 스키마가 필요하지 않은 텍스트 형식입니다. Protocol Buffers는 필수 스키마(.proto)가 있는 바이너리 형식으로 크기가 훨씬 작고 속도가 더 빠릅니다. Protobuf는 고부하 시스템에 선택되고 JSON은 범용 호환성을 위해 선택됩니다.

JSON 대신 XML은 언제 사용되나요?

XML은 구성 파일(AndroidManifest, 레이아웃 리소스), 복잡한 중첩이 있는 문서 및 XSD를 통한 엄격한 검증이 필요한 시스템의 표준으로 남아 있습니다. XML은 네임스페이스 지원이 필요한 SOAP 프로토콜 및 레거시 시스템에서도 사용됩니다.

Swift에서 Codable이란 무엇인가요?

Codable은 자동 직렬화 및 역직렬화를 위해 Encodable과 Decodable을 결합한 Swift 프로토콜입니다. 컴파일러는 구조체 또는 클래스의 모든 속성에 대해 encode(to:) 및 init(from:) 메서드의 구현을 생성합니다.

Parcelable과 Serializable 중 무엇이 더 빠른가요?

Parcelable은 리플렉션을 사용하지 않고 바이트 스트림에 직접 필드를 쓰기 때문에 Serializable보다 훨씬 빠르게 작동합니다. 최신 장치에서는 Parcelable 쪽이 최대 10배까지 빠를 수 있습니다.

요약

  • 직렬화 — 전송을 위해 객체를 형식으로 변환, 역직렬화 — 역 복원
  • JSON — REST API 및 모바일 애플리케이션에서 사용되는 범용 텍스트 형식
  • Protocol Buffers — 고정 스키마를 가진 고성능 시나리오를 위한 Google의 바이너리 형식
  • XML — XSD 검증이 있는 형식, 구성 및 레거시 시스템에서 사용
  • Parcelable(Android)Codable(iOS) — 구성 요소 간 데이터 전송을 위한 플랫폼별 직렬화 메커니즘
  • 직렬화 보안은 중요합니다: 신뢰할 수 없는 데이터는 역직렬화 취약점으로 이어질 수 있습니다

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기