serial version UID

서노·2022년 10월 23일

먼저 자바는 JVM을 이용하여 자바코드를 컴파일하여 바이트 코드로 만들어냅니다. 그리고 자바의 Object를 바이트 코드로 변경한 기술을 직렬화(Serialize)라 하고, 바이트 코드로 된 Object를 다시 자바의 Object로 읽을 수 있도록 변환된 기술을 역직렬화(Deserialize)라고 합니다. 이는 프로그램 간 데이터 전송은 객체건 뭐건 결국 바이트의 흐름으로 전송하는 데 자바 프로그램에서 바이트 데이터를 다시 읽었을 때 자바의 객체로 읽어내기 위한 기술입니다.

  • 직렬화: JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술
  • 역직렬화: 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태.

자바에서 직렬화 하기 위한 방법은 java.io.Serializable 인터페이스를 상속받고 상속받은 객체는 직렬화 할 수 있는 기본 조건이 됩니다.

하지만 중요한 점은 직렬화와 역직렬화를 진행하는 시스템이 서로 다를 수 있다는 것을 반드시 고려해야 합니다. 코드는 시간이 갈수록 변하기에 시간에 따라 코드가 변함에도 불구하고 객체의 버전을 유지하기 위해선 자바 코드 모델의 버전간의 호환성을 유지하기 위한 SUID(serialVersionUID)를 정의해야 합니다.

private static final long serialVersionUID = -6120832682080437368L;

와 같이 클래스에 직접 SUID 값을 지정해버리면 JVM에서 SUID 생성 알고리즘을 사용하지 않고 이 값을 사용하게 되므로 버전에 따른 불일치 에러는 막을 수 있습니다.

만약 SUID를 지정안하면 자바 내부적으로 SUID를 생성합니다. Default SUID는 클래스의 기본 해쉬값을 사용하고, 사용 알고리즘은 Java(TM) Object Serialization Specification 정의된 것을 따른다고 합니다.

그러나 모든 serialization이 필요한 클래스에는 명시적으로 serialVersionUID를 선언해줄것을 강력하게 권유하고 있습니다.

왜냐하면 디폴트 serialVersionUID 계산은 클래스의 세부 사항을 매우 민감하게 반영하기 하고, 컴파일러 구현체에 따라서 달라질 수 있어 역직렬화 과정에서 예상하지 못한 InvalidClassExceptions이 발생될 수 있기 때문입니다.

하지만 serialVersionUID을 붙여주어도 아래와 같이 호환성 문제가 발생되는 경우가 있을 수 있습니다.

SUID 사용해도 호환성 문제가 발생되는 경우

  • instance variable의 삭제
  • instance variable의 type 변경
  • instance variable의 transient 지정
  • instance variable의 static 지정
  • class의 serializable 구현 취소
  • class의 상속 tree 변경

SUID 사용해도 호환성 발생하지 않는 경우

  • instance variable의 추가
  • instance variable의 transient 지정 취소
  • instance variable 접근 level이 deserialize 시 값을 대입하는데 문제 없을 경우
  • 상속 tree에서 class 추가
  • 상속 tree에서 class 삭제

자바 직렬화 용도

  1. 세션을 서블릿 메모리위에 동작을 할 때 직렬화가 따로 필요로 하지 않지만, 파일로 저장하거나 세션 클러스터링, DB를 저장하는 옵션 등을 선택하게 되면 세션 자체가 직렬화가 되어 저장되어 전달
    • 세션에 필요한 객체는 java.io.Serializable 인터페이스를 구현(implements) 해두는 것을 추천
  2. Encache, Redis, Memcached라이브러리 시스템에서 많이 사용
    • 메모리, 외부 저장소, 파일 등을 저장소를 이용해서 데이터 객체를 저장한 후 동일한 요청이 오면 DB를 다시 요청하는 것이 아니라 저장된 객체를 찾아서 응답하게 하는 형태를 보통 캐시를 사용
  3. 자바 RMI(Remote Method Invocation): 원격 시스템간의 메시지 교환을 위해서 사용하는 자바 기술

정리

  1. 외부 저장소로 저장되는 데이터는 짧은 만료시간의 데이터를 제외하고 자바 직렬화를 사용을 지양합니다.
  2. 역질렬화시 반드시 예외가 생긴다는 것을 생각하고 개발합니다.
  3. 자주 변경되는 비즈니스적인 데이터를 직렬화를 사용하지 않습니다.
  4. 긴 만료 시간을 가지는 데이터는 JSON 등 다른 포맷을 사용하여 저장합니다.

참조링크

profile
무엇을 할라까

0개의 댓글