Serialize, 제대로 알고 쓰기

박근수·2024년 12월 1일
0

01. 자바 직렬화의 대안을 찾아라

Serialize

Json,Protocol buffer

JSONProtocol Buff
JavaScript Object Notation
경량데이터 교환 형식
데이터를 인코딩 하는 방법
Google에서 구조화된 데이터의 직력 / 역직렬화 위해 개발
No schema메세지를 정의하고, 교환하기 위한 규칙 필요
Test 형식 (key, value쌍)Binary
가볍고 다른 직렬화 기술들보다 빠름Json보다 빠름
문자열, 숫자, Json객체, 배열, boolean, null
(class와 function 지원하지 않음)
폭 넓은 데이터 유형 지원

JSON, 때떄로 필요할 때 Protocol Buff 기반을 사용하고, 직렬화는 그만 보내주도록 하자. 새로운 시스템에서 직렬화를 사용할 이유가 없다.

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

Warning Point

  1. 일단 구현하고 나면 돌이킬 수가 없다 (이미 해당 스펙을 구현하고 있다로 알기 떄문)
  2. 버그와 보안 구멍이 생길 위험이 높아진다. (우회 객체 생성)
  3. 테스트 범위가 늘어난다. (serilize 검사)
  4. 상속용으로 설게뙨 클래스는 대부분 Serializable을 구현하면 안되며, 인퍼테이스 또한 마찬가지
  5. 내부 클래스는 직렬화를 구현하지 말아야 한다.

readObject 메서드는 방어적으로 사용하라

  • Private 이어야 하는 객체 참조 필드는 각 필드가 가리키는 개체를 방어적으로 복사하라. (immutable class 내의 가변 요소)
  • 모든 불변식으로 검사하여 어긋나는 것이 발견되면 invalidObjectException을 던진다.
  • Deserialize 후 Object Graph의 유효성을 검사해야 한다면 ObjectInputValidation Interface 사용
  • 직/간접적으로 재정의할 수 있는 메서드는 호출하지 말자

readResolve

싱글톤 형태를 유지하기 위함
Deserialize중에 readObject 메서드가 존재하더라도 readResolve 메서드에서 반환한 인스턴스로 대체
(readObject를 통해 만들어진 건 바로 객체 참조가 사라짐)

readResolve를 인스턴스 통제 목적으로 사용한다면 객체 참조 타입 인스턴스 필드는 모두 trasient로 선언

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

Proxy Pattern

Sample Code

public class Item90{
	public static void main(String[] args){
    	Subject proxy = new Proxy();
        proxy.request();
    }
}

interface Subject{ 
	void request(); 
}

class RealSuject implements Subject{
	@Override
    public vodi request(){
    	System.out.println("hello world");
    }
}

class Proxy implements Subject{

	Subject subject;
    
    @Override
    public void request(){
    	if(subject == null){
        	subject = new RealSubject();
            subject.request();
        }
    }
}

3자가 확장할 수 없는 클래스라면 직렬화 프록시 패턴을 권장
(불변식을 안정저긍로 직렬화 할 수 있음)
단, 클라이언트가 확장할 수 있는 클래스에는 적용 불가, 순환관계의 클래스에 호출 불가

profile
개발블로그

0개의 댓글