본문 바로가기
백엔드/Java

Effective Java 맛보기 11탄

by david100gom 2019. 9. 21.

직렬화

  1. 자바 직렬화의 대안을 찾으라

    • 직렬화는 위험하니 피해야 한다. 시스템을 밑바닥부터 설계한다면 JSON이나 프로토콜 버퍼와 같은 대안을 사용하자. 신뢰할 수 없는 데이터는 역직렬화하지 말자. 꼭 해야 한다면 객체 역직렬화 필터링을 사용하되, 이마저도 모든 공격을 막아줄 수는 없음을 기억하자. 클래스가 직렬화를 지원하도록 만들지 말고, 꼭 그렇게 만들어야 한다면 정말 신경써서 작성해야 한다.

  2. Serializable을 구현할지는 신중히 결정하라

    • Serializable은 구현한다고 선언하기는 아주 쉽지만, 그것은 눈속임일 뿐이다. 한 클래스의 여러 버전이 상호작용할 일이 없고 서버가 신뢰할 수 없는 데이터에 노출될 가능성이 없는 등, 보호된 환경에서만 쓰일 클래스가 아니라면 Serializable구현은 아주 신중하게 이뤄져야 한다. 상속할 수 있는 클래스라면 주의사항이 더욱 많아진다.

  3. 커스텀 직렬화 형태를 고려해보라

    • 클래스를 직렬화하기로 했다면 어떤 직렬화 형태를 사용할지 심사숙고하기 바란다. 자바의 기본 직렬화 형태는 객체를 직렬화한 결과가 해당 객체의 논리적 표현에 부합할 때만 사용하고, 그렇지 않으면 객체를 적절히 설명하는 커스텀 직렬화 형태를 고안하라. 직렬화 형태도 공개 메서드를 설계할 때에 준하는 시간을 들여 설계해야 한다. 한번 공개된 메서드는 향후 릴리스에서 제거할 수 없듯이, 직렬화 형태에 포함된 필드도 마음대로 제거할 수 없다. 직렬화 호환성을 유지하기 위해 영원히 지원해야 하는 것이다. 잘못된 직렬화 형태를 선택하면 해당 클래스이 복잡성과 성능에 영구히 부정적인 영향을 남긴다.

  4. readObject 메서드는 방어적으로 작성하라

    • readObject메서드를 작성할 때는 언제나 public 생성자를 작성하는 자세로 임해야 한다. readObject는 어떤 바이트 스트림이 넘어오더라도 유효한 인스턴스를 만들어내야 한다. 바이트 스트림이 진짜 직렬화된 인스턴스라고 가정해서는 안된다. 이번 아이템에서는 기본 직렬화 형태를 사용한 클래스를 예로 들었지만 커스텀 직렬화를 사용하더라도 모든 문제가 그래도 발생할 수 있다. 이어서 안전한 readObject 메서드를 작성하는 지침을 요약해 보았다.

      • private 이어야 하는 객체 참조 필드는 각 필드가 가리키는 객체를 방어적으로 복사하라. 불변 클래스내의 가변 요소가 여기에 속한다.

      • 모든 불변식을 검사하여 어긋나는 게 발견되면 InvalidObjectException을 던진다. 방어적 복사 다음에는 반드시 불변식 검사가 뒤따라야 한다.

      • 역직렬화 후 객체 그래프 전체의 유효성을 검사해야 한다면 ObjectInputValidataion 인터페이스를 사용하라(이 책에서는 다루지 않는다)

      • 직접적이든 간접적이든, 재정의할 수 있는 메서드는 호출하지 말자

  5. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라

    • 불변식을 지키기 위해 인스턴스를 통제해야 한다면 가능한 한 열거타입을 사용하자. 여의치 않은 상황에서 직렬화와 인스턴스 통제가 모두 필요하다면 readResolve 메서드를 작성해 넣어야 하고, 그 클래스에서 모든 참조 타입 인스턴스 필드를 transient로 선언해야 한다.

  6. 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라

    • 제 3자가 확장할 수 없는 클래스라면 가능한 한 직렬화 프록시 패턴을 사용하자. 이 패턴이 아마도 중요한 불변식을 안정적으로 직렬화해주는 가장 쉬운 방법일 것이다.

 

Forward Proxy
클라이언트가 example.com 에 연결하려고 하면 사용자 PC가 직접 연결하는게 아니라 포워드 프록시 서버가 요청을 받아서 example.com 에 연결하여 그 결과를 클라이언트에 전달(forward) 해 준다.

Reverse Proxy
클라이언트가 example.com 웹 서비스에 데이타를 요청하면 Reverse Proxy는 이 요청을 받아서 내부 서버에서 데이타를 받은후에 이 데이타를 클라이언트에 전달하게 된다.

 

참조서적 및 페이지

댓글