Skip to content

[아이템 90] 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라 #105

Description

@jupyter471

📌 [아이템 90] 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라

✨ 핵심 내용

직렬화 프록시 패턴을 통해 Serializable의 위험을 크게 줄일 수 있다

⭐  1. 바깥 클래스의 논리적 상태를 정밀하게 표현하는 중첩 클래스를 설계해 private static으로 선언한다

⇒ 이때 중첩 클래스가 바깥 클래스의 직렬화 프록시다

  • 중첩 클래스의 생성자는 단 하나여야하고 바깥 클래스를 매개변수로 받아야한다
    • 인스턴스의 데이터를 복사함
private static class Serializationproxy implements Serializable {
		private final Date start;
		private final Date end;
		
		**SerializationProxy**(Period p) {
				this.start = p.start;
				this.end = p.end;
		}
		
		private static final long serialVersionUID =
							234098243823485285L; // 아무 값이나 상관없다. (아이템87)
}
  1. 바깥 클래스에 writeReplace 메서드를 추가한다
//직렬화 프록시 패턴용 writeReplace 메서드
private Object writeReplace() {
		return new SerializationProxy(this);
}

→ 자바의 직렬화 시스템이 바깥 클래스의 인스턴스 대신 SerializationProxy의 인스턴스를 반환하게 하는 역할을 함

즉, 직렬화가 이뤄지기 전에 바깥 클래스 인스턴스를 직렬화 프록시로 변환해줌

//직렬화 프록시 패턴용 readObject 메서드
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
				throw new InvalidObjectException("프록시가 필요합니다.");
}

→ 해당 메서드를 바깥 클래스에 추가하면 불변식 훼손 공격을 막을 수 있다

  1. 바깥 클래스와 논리적으로 동일한 인스턴스를 반환하는 readResolve 메서드를 SerializationProxy 클래스에 추가한다

    → 역직렬화 시 직렬화 시스템이 직렬화 프록시를 다시 바깥 클래스의 인스턴스로 변환하게 해준다

직렬화는 생성자를 이용하지 않고 인스턴스를 생성하는데, 해당 패턴은 이러한 상당 부분을 제거한다!

⇒ 일반 인스턴스를 만들 때와 똑같은 생성자, 정적 팩터리, 혹은 다른 메서드를 사용해 역직렬화된 인스턴스를 생성한다

→ 역직렬화된 인스턴스가 해당 클래스의 불변식을 만족하는지 검사할 다른 수단 필요 X

  • 직렬화 프록시는 필드를 final로 선언해도되므로 클래스를 불변으로 만들 수 있다
  • 직렬화 프록시 패턴은 역직렬화한 인스턴스와 원래의 직렬화된 인스턴스의 클래스가 달라도 정상 작동한다!
  • ex) EnumSet

직렬화 프록시 패턴의 한계

  1. 클라이언트가 멋대로 확장할 수 있는 클래스(아이템 19)에는 적용할 수 없다
  2. 객체 그래프에 순환이 있는 클래스에 적용할 수 없다
  3. 대가가 따른다! 느리다!

💡 새롭게 알게 된 점

  • 학습하면서 이전과 다르게 이해한 점이나 새롭게 알게 된 개념을 공유해주세요.

📚 정리

제3자가 확장할 수 없는 클래스라면 가능한 한 직렬화 프록시 패턴을 사용!


📢 댓글로 각자의 학습 내용을 공유해주세요!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions