1. 직렬화와 역직렬화
2. 실제로 직렬화를 실시해보자
3. 특정 정보는 제외하고 직렬화를 실시해보자
4. 역직렬화 주의점
5. 직렬화 단점
Android 개발을 하다 보면 Intent 를 통해 다른 Android 컴포넌트에 정보를 전달해야할 때가 있다. 이 때 primitive Type 인 int, String, double 과 같은 데이터는 Intent 에 바로 담을 수 있는데, 객체를 통째로 넘기려면 해당 객체에 Serializable 인터페이스를 구현해야 하는 경우가 생긴다. 그렇다면 Serialization 이 도대체 뭘까?
1. 직렬화와 역직렬화
Java나 Kotlin, Swift 같은 객체 지향 언어에서는 모든 데이터들을 객체로 표현한다. 그렇다면 Java 나 Kotlin 으로 만든 프로그램의 데이터 (객체) 를 외부로 전송하려면 어떻게 해야 할까?
기본적으로 Java 의 I/O 처리는 정수, 문자열, 바이트 단위의 처리만 지원하기 때문에, Java에서 만든 객체의 내용을 저장하거나 복원하기 위해선 I/O가 처리할 수 있는 형태로 객체를 변환해야 한다.
직렬화란 위와 같이 Java 의 데이터를 외부로 저장하거나 전송, 복원하기 위해서 I/O 가 처리할 수 있는 바이트 형태로 변환하는 기술을 의미한다.
반대로 역직렬화란, 바이트 형태로 변환된 데이터를 다시 Java 의 객체로 변환하는 기술을 의미한다.
직렬화의 특징
- 외부에 바이트 형태로 저장된 데이터는 언제든지 다시 불러들여 역직렬화를 통해 Java 에서 이해하는 객체로 변환할 수 있다.
- Java의 기본 라이브러리를 사용하지 않더라도 여러 형태로 직렬화를 수행할 수 있다. (CSV, JSON)
- Java에서 제공하는 직렬화 기능은 오로지 Java 프로그램끼리만 공유가 가능하고, 필드명을 수정하거나 자바 버전이 달라 클래스의 속성이 달라지면 사용할 수 없다.
- 직렬화된 데이터의 전송과 역직렬화는 모두 JVM이 처리하기 때문에, 프로그램이 실행되는 운영체제에 영향을 받지 않는다.
2. 실제로 직렬화를 실시해보자
클래스를 직렬화하기 위해선 기본적으로 Serializable 인터페이스를 구현해야 한다.
class Dog(val name: String, val age: Int) : Serializable
kotlin
그러나 Serializable 인터페이스를 구현하더라도 실제로 구현해야할 메서드는 없다.
해당 인터페이스를 구현함으로써, JVM에게 이 객체가 직렬화를 사용할 것이라고 알려주게 된다.
이제 이 클래스는 직렬화를 통해 외부 Java 프로그램에 전송되거나, 파일로 저장할 수 있다.
3. 특정 정보는 제외하고 직렬화를 실시해보자
만약에 다음과 같은 데이터를 파일로 저장하거나, 네트워크로 전송해야 한다고 생각해보자
public class PaymentInfo implements Serializable {
private String cardNumber;
private int price;
private String payDay;
private String cardIssuer;
}
java
위 클래스는 결제 정보 클래스로, 카드번호, 가격, 결제일자와 카드사의 정보를 담고 있다. 카드 번호는 민감한 정보라 카드 번호만 빼고 직렬화를 실시하려면 어떻게 해야 할까?
저장하고 싶지 않은 프로퍼티에 static 키워드나 transient 키워드를 붙이면 제외할 수 있다.
public class PaymentInfo implements Serializable {
static private String cardNumber;
transient private int price;
private String payDay;
private String cardIssuer;
}
4. 역직렬화 주의점
역직렬화를 수행할 때 주의할 점이 있다.
역직렬화를 수행하기 위해선 직렬화한 클래스의 속성과 역직렬화를 통해 생성할 클래스의 속성이 일치해야 한다.
Java는 이를 serialVersionUID 필드를 통해 판단한다. 이 필드는 Serializble 인터페이스에 구현된 것으로, 직렬화를 선언한 클래스를 컴파일할 때 컴파일러가 클래스 구조 정보를 해시값으로 변환한 값을 자동으로 넣어준다.
serialVersionUID 는 기본적으로 클래스의 해시값을 가지는데, 수동으로 ID 를 부여함으로써 내용에 관계없이 동일 클래스로 인식시킬 수도 있다. 즉 직렬화를 수행할 클래스의 필드값이나 함수는 추가하거나 삭제할 수 있다. 그러나 기존 필드의 이름을 변경시켜선 안된다.
따라서 웬만하면 구조가 변하지 않을 클래스만 직렬화를 이용해 저장하도록 하자.
5. 직렬화 단점
단순히 인터페이스를 구현하는 것만으로 외부에 클래스를 저장하거나 전송할 수 있다는 점에서 직렬화는 매력적으로만 보일지 모른다. 그러나 항상 개발자의 노동을 줄이는 기법은 추가적인 오버헤드가 붙기 마련이다.
간단한 객체를 직렬화 할 경우에도 클래스의 구조 정보나 다른 데이터의 정보가 포함되기 때문에 데이터의 크기가 많이 커지는 단점이 있다.
따라서 오랜 시간 동안 저장해야 하는 데이터의 경우엔 JSON 같은 다른 포맷을 사용하여 저장하는 것이 훨씬 좋다
[참고]
Comment