Serializable을 구현한 클래스를 만들면서 기본 직렬화 형식을 그대로 이용하면, 기존 구현을 완전히 내버리기란 불가능해진다. 그 직렬화 형식에 영원히 갇히게 된다는 뜻이다. 어떤 직렬화 형ㅅ힉이 적절할지 따져보지도 않고 기본 직렬화 형식을 그대로 받아들이지 말아야 한다. 


 기본 직렬화 형식은 그 객체의 물리적 표현이 논리적 내용과 동일할 때만 적절하다. 예를 들어 아래의 클래스를 보자.


 논리적으로 위의 클래스는 어떤 사람의 이름은 성,이름,그리고 중간이름으로 나타내며, 실제 물리적인 구현도 그렇게 되어 있다. 따라서 기본 직렬화형식으로 직렬화를 하는 것이 적절한 경우이다.

위의 클래스는 문자열의 리스트를 나타내는 클래스다. 객체의 물리적 표현 형태(양방향 연결리스트)가 논리적 내용과 많이 다를 경우 기본직렬화 형식을 받아들이면 문제가 생길 수 있다.

  • 공개 API가 현재 내부 표현 형태에 영원히 종속된다. 위 예제에서 private로 선언된 StringList,Entry 클래스는 public API의 일부분이 되어 버린다. 다음번 릴리즈에는 다른 내부 표현 방식을 채택하더라도 StringList클래스는 여전히 연결리스트 표현을 입력으로 사용해야 할 것이다.
  • 너무 많은 공간을 차지하는 문제가 생길 수 있다. 위 예제의 기본 직렬화 형식에는 리스트 항목 사이의 모든 연결 정보가 쓸데없이 들어가 있다. 이런 정보는 구현 세부사항으로, 직렬화 형식에 포함시킬 가치가 없다.
  • 너무 많은 시간을 소비하는 문제가 생길 수 있다. 많은 양의 그래프를 순회할 수 있다. 위의 예제에서는 next를 따라가는 정도로 충분.
  • 스택 오버플로 문제가 생길 수 있다. 기본 직렬화 절차는 재귀적인 객체 그래프 순회를 필요로 하는데, 설사 객체 그 그래프의 크기가 과도한 수준이 아니라해도 오버플로가 생길 수 있다.

객체의 모든 필드가 transient일 때는 defaultWriteObject나 defaultReadObject를 호출하지 않는 것도 기술적으로 가능하긴 하지만 권장하는 사항은 아니다. 나중에 [비-transient객체 필드를 추가하더라도 상위 및 하위 호환성이 유지되기 때문이다.


기본 직렬화 형식 사용 여부에 상관없이, 객체를 직렬화 할 때는 객체의 상태 전부를 읽는 메서드에 적용할 동기화 수단을 반드시 적용해야 한다.



어떤 직렬화 형식을 이용하건, 직렬화 가능 클래스를 구현할 때는 직렬 버전UID를 명시적으로 선언해야 한다.


요약

직렬화 가능한 클래스를 만들기로 했다면 직렬화 형식에 대해서도 심각하게 고민해야 한다는 것이다. 기본 직렬화 형식은 그 형태가 객체의 논리적 상태에 부합할 때만 이용하라. 그렇지 않다면 객체의 논리적 상태를 적절히 표현하는 사용자 정의 직렬화 형식을 만들라. 일단 공개된 메서드는 향후 버전에서 제거할 수 없듯이, 직렬화 형식에 포함시킨 필드는 나중에 제거할 수 없다.





+ Recent posts