링크) https://techblog.woowahan.com/2551/
자바의 직렬화 기술에 대한 대한 두 번째 이야기입니다.실제 자바 직렬화를 실무에 적용해보면서 주의해야 할 부분에 대해 이야기해보려고합니다.
자바 직렬화는 자바 개발자 입장에서는 상당히 쉽고 빠르게 사용할 수 있도록 만든 기술입니다.
JSON 또는 CSV 등 형태의 포맷을 이용하면 직렬화 또는 역직렬화시에 특정 라이브러리를 도입해야 쉽게 개발이 가능하며,구조가 복잡하면 직접 매핑시켜줘야 하는 작업도 포함하게 됩니다.그것에 비해 자바 직렬화는 비교적 복잡한 객체도 큰 작업 없이 (java.io.Serializable 인터페이스만 구현해주면)기본 자바 라이브러리만 사용해도 직렬화와 역직렬화를 할 수 있습니다.
하지만 등가교환이라는 말이 있듯이 쉽게 이용할 수 있는 만큼 실제 업무에서 사용할 때에는 신경 써야 하는 부분이 있습니다.제 경험에 빗대어서 신경 써야 할 부분에 대해 몇 가지 이야기해보겠습니다.
앞서서 예시를 들은 woowahan.blog.exam1.Member (이하 Member) 클래스를 기준으로 이야기해보겠습니다.
public class Member implements Serializable {
private String name;
private String email;
private int age;
// 생략
}
예제에서 Member 클래스가 있습니다. 이 클래스의 객체를 직렬화 시켜보겠습니다.아래에의 문자열은 직렬화된 Member 클래스의 객체 문자열입니다. 테스트에 용의 하도록 Base64로 인코딩하였습니다.
Base64.getEncoder().encodeToString(serializedMember);
rO0ABXNyABp3b293YWhhbi5ibG9nLmV4YW0xLk1lbWJlcgAAAAAAAAABAgAESQADYWdlSQAEYWdlMkwABWVtYWlsdAASTGphdmEvbGFuZy9TdHJpbmc7TAAEbmFtZXEAfgABeHAAAAAZAAAAAHQAFmRlbGl2ZXJ5a2ltQGJhZW1pbi5jb210AAnquYDrsLDrr7w=
이 문자열을 바로 역직렬화 시키면 바로 Member 객체로 변환합니다. (테스트할 때에는 반드시 패키지도 동일해야 합니다.)
Member 클래스의 구조 변경에 대한 문제를 확인해보겠습니다.
public class Member implements Serializable {
private String name;
private String email;
private int age;
// phone 속성을 추가
private String phone;
// 생략
}
우리가 보통 원하는 것은 phone 멤버 변수가 추가되어도 기존 멤버 변수의 기존 멤버 변수는 채워지길 원합니다. phone은 null 되어 있더라도 말이죠.이전에 자바 직렬화된 데이터를 역직렬화 시켜 보겠습니다.
java.io.InvalidClassException: woowahan.blog.exam1.Member; local class incompatible: stream classdesc serialVersionUID = -8896802588094338594, local class serialVersionUID = 7127171927132876450
이렇게 클래스의 멤버 변수 하나만 추가되어도 java.io.InvalidClassException 예외가 발생합니다.예외 메시지를 읽어보면 serialVersionUID의 정보가 일치하지 않기 때문에 발생한 것을 알 수 있습니다.우리는 Member 클래스에서는 serialVersionUID 의 값을 -8896802588094338594 정보로 설정해준 적도 없으며,7127171927132876450으로 변경한 적도 없습니다. 어떻게 된 일일까요?
그래서 자바 직렬화 스펙을 확인해보았습니다. (링크)