5. 자바의 직렬화/역직렬화
목차
직렬화란
직렬화를 하는 이유?
참조 자료형의 경우, stack에는
주소
(실제 데이터가 담긴 heap영역 주소)가 담겨있다. 이 객체를 파일에 저장한다고 하면 주소값이 저장된다. 만약 프로그램 종료 후/혹은 네트워크 통신을 하게 될 경우, 이 메모리 주소값은 다른 객체를 가리키므로 의미없는 데이터가 된다. 따라서 객체를 저장/전송할 때는실제 데이터들
을 찾아 저장해야 한다.
직렬화하는 방법
Serializable
java.io.Serializable
인터페이스를 implements한다.구현할 부분은 없고, 해당 클래스가 직렬화가 제공되어야 함만을 JVM에게 알려주는 역할을 한다.
ObjectStream
객체를 JVM 외부로 내보내거나, 외부 객체를 JVM 내부로 읽을 때 사용하는
Stream
이다.ObjectOutputStream : 객체에 직렬화를 수행해준다.
FileOutputStream : 직렬화한 내용을 저장할 파일을 생성해준다.
객체를 직렬화하고 파일로 저장하면 다음과 같다.
Transient
직렬화에서 제외하고 싶은 경우 선언하는 키워드이다.
보안 상의 이유로 저장하지 않거나(비밀번호, 주민번호 등), 저장할 필요가 없는 임시 데이터인 경우 직렬화 과정에서 제외하기 위해 사용한다.
private transient String password;
// 필드는 유지되고, 값은 null로 대입된다.
역직렬화
아래는 직렬화된 파일을 읽어, 객체 형태로 복원하였다.
이렇게 역직렬화 시, 직렬화한 클래스와 역직렬화하는 클래스의 멤버필드/타입이 일치해야 한다. 이를 판단하기 위해 serialVersionUID
필드를 사용한다.
serialVersionUID
직렬화와 역직렬화 과정에서 값이 서로 맞는지 확인하기 위해 사용하는 멤버 필드이다.
직렬화할 때 직접 선언해주지 않으면, 자동으로 클래스의 기본 해쉬값을
serialVersionUID
로 사용한다.직접 선언해줄 경우, 클래스 구조에 변경이 생기더라도 역직렬화를 사용할 수 있다.
클래스 정보가 달라지면, serialVersionUID
가 변경된다. 역직렬화 시 serialVersionUID
이 똑같지 않다면 InvalidClassException
예외가 발생한다! 자바 직렬화는 클래스 속성 변화에 엄격하다. int → long으로 타입 하나만 바꾸어도 클래스 구조가 바뀌었다고 판단하여 serialVersionUID
가 달라진다. 따라서 변경될 수 있는 클래스에서는 자바 직렬화 대신 XML, JSON과 같은 포맷을 이용한 직렬화를 사용하는 것이 좋다.
정리하면
자바 직렬화는 멤버 변수 추가/타입 변경 등 변경에 엄격하다. 따라서 자주 변경되거나 오래 저장될 클래스에서는 지양하는 것이 좋다. 자바 직렬화는 짧은 만료 시간을 가지거나, 변경되지 않는 데이터를 객체화할 때 사용하는 게 좋다.
변경될 여지가 많은 클래스는 XML, JSON과 같은 포맷을 이용한 직렬화를 사용하는 게 좋다.
Reference
Last updated