brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Oct 29. 2018

직렬화(Serialization)

#78 직렬화된 인스턴스 대신 직렬화 프록시의 사용을 고려하자

Effective Java - 직렬화(Serialization)


#78 직렬화된 인스턴스 대신 직렬화 프록시의 사용을 고려하자


이제까지 직렬화로 인해 발생할 수 있는 여러 가지 문제들과 이에 대한 방안에 대해 다뤘습니다.

이 책의 마지막이자 또 다른 방안으로 직렬화 프록시 패턴(serialization proxy pattern)이 있습니다.


직렬화 프록시 패턴에 대해 알아보겠습니다.




#01 Period class


1. private static 중첩 클래스(SerializableProxy) 설계 - 직렬화 프록시


2. 외곽 클래스(Period)와 중첩 클래스(SerializationProxy)에 Serializable 인터페이스를 구현


3. 중첩 클래스는 외곽 클래스의 매개 변수 타입으로 하는 단일 생성자를 가짐

SerializationProxy(Period p) {}


4. 자신의 인자로부터 데이터만 복사

SerializationProxy(Period p) {
    this.start = p.start;
    this.end = p.end;
}


5. 외곽 클래스에 writeReplace 메서드 추가

- 직렬화 메커니즘에서 외곽 클래스(Period) 인스턴스 대신 중첩 클래스(SerializationProxy) 인스턴스를 직렬화 한다.

- 즉, 외곽 클래스 인스턴스를 직렬화 프록시로 변환

private Object writeReplace() {
    return new SerializationProxy(this);
}


6. 외곽 클래스의 불변 규칙을 깨기 위한 시도를 막기 위해 readObject 메서드 추가

private void readObject(ObjectInputStream stream) throws InvalidObjectException {
    throw new InvalidObjectException("Proxy required");
}


7. 중첩 클래스에 readResolve 메서드 추가

- 역직렬화시 직렬화 프록시를 외곽 클래스 인스턴스로 역 변환한다.

private Object readResolve() {
    return new Period(start, end);
}


#02 Period class


readResolve 메서드는 외곽 클래스의 public 생성자만을 이용해 외곽 클래스(Period) 인스턴스를 생성합니다.

즉, 언어 외부의 영역인 직렬화 메커니즘이 아닌 동일한 생성자를 통해 역직렬 화한 인스턴스를 생성하기 때문에, 인자 검사나 방어 복사가 필요 없습니다.




이전에 작성했던 방어 가능한 readObject 메서드 작성보다 직렬화 프록시 패턴 구현이 더 쉽고 신경 쓸 부분도 적습니다.

하지만 방어 가능한 readObject 보다 성능은 더 좋지 않다는 단점이 있습니다.

매거진의 이전글 직렬화(Serialization)
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari