[Java] serialversionUID

김주경·2021년 10월 5일
0
post-thumbnail

Map 계열, 또 list 계열의 클래스들을 implements 혹은 extends 해서 클래스를 만들다 보면
serialversionUID 이라는 static 변수를 마주하게 된다.
이 녀석에 대해 알아보자

serialversionUID 란 무엇인가?

우선 이 친구를 이해하기 위해서 자바 직렬화에 대해 알고와야 한다.
자바 직렬화에 대해 알아보긔 - 내 벨로그

serialversionUID는 Serializable 인터페이스를 구현햇을 때 할당하라고 나온다.

우선 특징은 다음과 같다.

  • class의 versioning 용도로 사용됨.
  • 직렬화 시, 사용자가 특정 값을 지정해 주지 않으면 자동으로 번호를 생성한다.
  • 직렬화, 역직렬화 시 이 값을 기준으로 같은 class인지 확인하며, 이 번호가 다를 경우 InvalidClassException을 토해낸다.

자동생성 대신, 직접 지정해주자.

(앞으로 serialversionUID는 SUID로 통칭한다.)

앞서 특징에서 살펴 봤 듯, 이 친구는 내가 따로 지정해주지 않으면 컴파일러가 고유값을 만들어 지정한다.
알아서 자동으로 지정해주는데 굳이 특정값을 지정해줘야 할까?

해주자. 직렬화-역직렬화 시 SUID를 기준으로 해당 객체가 같은 객체인지 아닌지를 판단한다. 만일 이를 자동생성으로 내비두면, 아래와 같은 문제가 발생할 수 있다.

극단적이고 많은 것이 생략되어있지만 한 번 예를 들어보자.
쉽고 간딴하게 각각 A와 B라는 자바 서버가 각자 구동되고 있다고 가정해보자. A에서 B로 Car라는 객체를 전송할 예정이다. B에 있는 Car 객체는 A 객체보다 필드에 변수가 하나 더 존재한다.
아래 그림처럼 A 자바의 Car 객체는 byte stream로 직렬화 되어 B로 넘겨지고 이 byte stream을 B의 Car 객체로 역직렬화 하는 상황이다.

만일 이 Car 객체에 SUID를 별도로 지정해주지 않았다고 가정해보자. 그리고 A와 B 각각의 컴파일러는 임의로 Car 객체에 SUID를 생성한다. 이 때 A의 Car.java에 임의생성된 SUID 는 1178945315L 이고, B에 생성된 SUID는 314826397L 이다. 직렬화된 A의 byte stream이 B로 도착해 Car 객체로 역직렬화를 하는 과정에서, 서로의 SUID를 비교하게 된다. 하지만 각각 1178945315L와 314826397L로 다른 SUID를 가지고 있기 때문에, B서버에서는 해당 직렬화된 Car 객체를 같은 객체라고 인식하지 못하게 된다.

그럼 모다시경? -> 에러를 뿜는다.

만일 위의 상황에서 SUID를 지정해주었다면, oil_type이라는 변수가 null로 처리 될 뿐 에러는 뜨지 않았을 것이다.
또 다른 상황을 가정하자면, 만일 모든 필드변수가 똑같은 상황이라 할지라도 SUID가 다르면 에러가 나왔을 것이다.

SUID와 Versioning

조금 더 실무에서 활용할만한 예시를 들어보자.

위에서처럼 Car라는 클래스를 만들었는데, 프로그램이 업데이트 되면서 max_speed 라는 필드변수가 추가 되었다고 가정하자.

이 경우, 만일 SUID를 지정했다면, 이전 버전에서 새 버전으로 직렬화-역직렬화를 해도 이상이 없을 것이다. (물론 이것은 새로 추가된 변수가 사용되지 않는 로직에서만 국한된다. 추가로 새버전에서 구버전으로 데이터를 보낼때는 문제가 생길 수 있다.)
반대로 기존의 필드객체를 삭제해도 SUID 관리를 해준다면 에러가 발생하지 않는다.

하지만 이렇게 SUID를 지정해줘도 변수의 타입이 변경된다면(int -> Integer도 용납안함) 또 역직렬화 못한다고 난리를 친다.

결론

그냥 JSON 쓰자.

profile
안냐세온

0개의 댓글