티스토리 뷰

반응형

Serializable

  • Serializable 인터페이스의 구현 클래스는 인스턴스를 직렬화할 수 있다.
  • Serializable 구현은 아주 값비싼 일

 

 

Serializable 구현 후 릴리스한 뒤에는 수정이 어려움

  • 직렬화 형태도 하나의 공개 API가 되어 영원히 지원해야함
    • 자바의 기본 직렬화 형태에서는 클래스의 private, protected 필드들도 API로 공개되어 캡슐화가 깨짐
    • 뒤늦게 클래스 내부 구현을 손보면 원래의 직렬화 형태와 달라지게되어 안됨
    • 직렬화 가능 클래스를 만들고자 한다면 고품질의 직렬화 형태도 주의해서 함께 설계해야함 [아이템 87,90]
  • 모든 직렬화된 클래스는 고유 식별 번호를 부여받고 (serialVersionUID라는 static final long 필드), 이 번호를 명시하지 않으면 시스템이 런타임에 암호 해시함수를 적용하여 자동으로 클래스 안에 생성해 넣음
    • 이 값 생성에는 클래스 이름, 구현 인터페이스들, 컴파일러가 자동으로 생성해넣은 것을 포함한 대부분의 클래스 멤버들 고려됨 → 나중에 클래스 내부 구현을 손보면 직렬 버전 UID값도 변함
    • 즉, 자동 생성 값에 의존하면 호환성이 깨져 런타임에 InvalidClassException 발생

 

 

Serializable 구현은 버그와 보안 구멍 위험이 높아짐

  • 직렬화는 언어의 기본 메커니즘(생성자로 객체를 만드는 것)을 우회하는 객체 생성 기법
  • 역직렬화는 일반 생성자의 문제가 그대로 적용되는 숨은 생성자 → 불변식 깨짐과 약한 보안 [아이템 88]

 

 

Serializable 구현은 해당 클래스의 신버전을 릴리스할 때 테스트할 것이 늘어남

  • 직렬화 가능 클래스가 수정되면 신버전 인스턴스를 직렬화 한 후 구버전으로 역직렬화할 수 있는지 테스트해야함 (반대도 마찬가지)
  • 클래스를 처음 설계할 때 커스텀 직렬화 형태를 잘 설계했다면 이런 테스트 부담을 줄일 수 있음 [아이템 87,90]

 

 

Serializable 구현 여부는 가볍게 결정할 사안이 아님

  • 객체를 전송/저장 시 자바 직렬화를 이용하는 프레임워크용 클래스나 직렬화를 반드시 구현해야하는 다른 클래스의 컴포넌트로 쓰일 클래스는 선택의 여지가 없음
  • Serializable 구현 비용이 적지 않으니 이득과 비용을 잘 따져서 설계하자.
  • 역사적으로 BigInteger과 Instant 값 클래스와 컬렉션 클래스들은 직렬화를 구현, 스레드 풀처럼 동작하는 객체를 표현하는 클래스는 직렬화 구현 x

 

 

상속용 클래스는 대부분 직렬화를 구현하면 안됨

  • 인터페이스도 대부분 Serializable을 확장해서는 안된다. 이 규칙을 어기면, 그런 클래스를 확장하거나 그런 인터페이스를 구현하는 이에게 큰 부담이됨
  • Serializable을 구현한 클래스만 지원하는 프레임워크를 사용할 때는 예외
  • 클래스의 인스턴스 필드가 직렬화와 확장이 모두 가능하다면, 인스턴스 필드 값 중 불변식을 보장해야할 게 있다면 하위 클래스에서는 반드시 finalize 메서드를 재정의하지 못하게 해야함 (finalize 를 자신이 재정의 하면서 final로 선언하면됨) → 안하면 finalizer 공격 당함 [아이템 8]
  • Serializable을 구현하지 않을 때는, 상속용 클래스인데 직렬화를 지원하지 않으면 그 하위 클래스에서 직렬화를 지원하려 할 때 부담이 늘어남 → 이런 클래스를 역직렬화하기 위해 그 상위클래스는 매개변수가 없는 생성자를 제공해야하는데 이런 생성자를 제공하지 않는다면 하위 클래스에서는 직렬화 프록시 패턴 [아이템 90] 사용해야만함.

 

 

내부 클래스는 직렬화를 구현하지 말아야함

  • 내부 클래스에는 바깥 인스턴스의 참조와 유효범위 안의 지역변수 값들을 저장하기 위해 컴파일러가 생성한 필드들이 자동 추가됨 → 이 필드들이 클래스 정의에 어떻게 추가되는지 정의되지 않았으므로 내부 클레스에 대한 직렬화 형태는 분명하지 않음
  • 정적 멤버 클래스는 직렬화를 구현해도됨

 

 

결론

  • 클래스의 여러버전이 상호작용할 일이 없고, 서버가 신뢰할 수 없는 데이터에 노출될 가능성이 없는 등, 보호될 환경에서만 쓰일 클래스가 아니라면 직렬화 구현은 신중해야함
  • 상속할 수 있는 클래스라면 더 주의해야함
반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday