현재 데이터의 상태를 영속적으로 저장하건, 다른 환경으로 전달(네트워크 통신)하기 위해 정해진 포맷으로 변환하는 과정
따라서 이렇게 변환된 데이터는 다시 원래 데이터로 변환이 가능함.(=역직렬화)
1) 데이터 타입이 기본형 타입이거나, 2) java.io.Serializable 인터페이스를 상속받아야 함.
@Entity
@AllArgsConstructor
@toString
public class Post implements Serializable {
private static final long serialVersionUID = 1L; // serialVersionUID를 직접 만듦
private String title;
private String content;
// ObjetOutputStream으로 직렬화 진행
// byte로 변환 값을 저장할 serializedPost 바이트배열을 선언
// ByteArrayOutputStream으로 Byte 배열로 전환한다.
Post post = new Post("제목", "내용");
byte[] serializedPost;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(post);
serializedPost = baos.toByteArray();
}
}
🤔 serialVersionUID 란?
- 시리얼 통신을 하는 클래스의 버젼 표시. 객체를 직렬화하여 바이트스트림으로 만들어 저장하는데, 이 안에는 serialVersionUID도 포함되게 된다. 이 후 역직렬화시, 다시 객체로 변환할 때 버전을 체크하게 된다. 이 때 사용되는 버전정보가 serialVersionUID다.
- 역직렬화 시, 자동으로 해시값이 할당된다. 다만 기본의 클래스 멤버 변수가 수정되면 serialVersionUID 값도 변경되어 직렬화에 문제가 생길 수 있다. 만약 변수 수정이 잦다면 직접 관리하는 것이 좋다.
// ObjectInputStream으로 serializedPost를 역직렬화함.
try (ByteArrayInputStream bais = new ByteArrayInputStream(serializedPost)) {
try (ObjectInputStream ois = new ObjectInputStream(bais)) {
Object objectPost = ois.readObject();
Post post = (Post) objectPost;
}
}
serialVersionUID는 개발자가 직접 관리한다.
클래스 변경을 개발자가 예측할 수 없는 경우, 직렬화 사용을 지양한다.
개발자가 직접 컨트롤할 수 없는 클래스, 자주 변경되는 클래스는 직렬화 사용을 지양한다.
역직렬화에 실패하는 상황에 대한 예외처리는 필수로 구현한다.
직렬화 데이터는 타입, 클래스의 메타정보를 포함한다. 따라서 사이즈가 크므로 트래픽으로 인한 비용이 증가될 수 있다. 때문에 직렬화 데이터 포맷보다 JSON포맷으로 변경하는 것이 더 좋다.