일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 인터럽트핸들러
- 개발자
- 빈 라인
- 딩코딩코
- mac 코드 블럭
- 2903
- hELLO 스킨
- 파이썬
- 백엔드
- CPU의 구성요소
- 코딩테스트
- 백준
- it세계의 괴물들
- CS지식
- 백엔드 면접지식
- 문자열
- 개발공부
- Roy Fielding
- 공부
- 비전공자
- 자바
- transiant
- LAMBDA
- 그림자 문제
- 카카오톡API
- Java
- AWS
- 알고리즘
- HTTP
- BOJ
- Today
- Total
아직은 NULL NULL 합니다
SerialVersionUID는 무엇이고 이를 선언해야 하는 이유가 무엇일까요? 본문
서론
안녕하세요. is낫널입니다.
나중에 이름을 바꾸게 될 수도 있지만 지금은 마음 가는 대로 짓게 된 이름인데 제 가치관을 표현해 줄 이름으로
생각해 내서 바꿔보려구요. 그게 이 블로그를 들어오는 사람들에게 제 이미지가 됐으면 좋겠네요!
오늘은 날이 되게 따뜻합니다. 이런 날도 이제 얼마 남지 않았어요. 곧 겨울이 올 것 같습니다.
12월이 되기 전에 취직을 해서 삿포로 가고 싶네요.
아 좀 주저리주저리 하는 타입이라, 의식의 흐름대로 말이 나오는 것 같습니다 ㅋㅋㅋ
이제 시작할게요.
SerialVersionUID를 선언해야 하는 이유
먼저 이 글을 들어온 이유로 이게 가장 궁금한 부분일 거 같습니다.
그래서 두괄식으로 결론부터 딱 내놓자면
직렬화 할 때와 역직렬화할 때 SerialVersionUID 라는 클래스의 버전이 일치해야 하기 때문입니다.
자세히 설명하자면, SerialVersionUID 라는 클래스의 버전은 객체가 직렬화될 때
클래스에 정의된 멤버변수의 정보를 이용해서 자동으로 생성되어 직렬화 내용에 포함됩니다.
그리고 역직렬화 할 때 클래스의 버전을 비교함으로써, 직렬화할 때의 클래스 버전과 일치하는지 확인할 수 있는 것입니다.
SerialVersionUID 의 값이 달라지는 이유
그렇다면, 왜 SerialVersionUID의 값이 달라지는 일이 발생하게 되는 걸까요?
보통 SerialVersionUID의 값이 자동으로 생성되는 데 있어, 역직렬화할 때 클래스의 버전이 갑자기 달라지는 경우가 크게 없지만
직렬화했던 클래스의 내용이 변경되었을 경우 새로운 SerialVersionUID 를 자동 생성하기 때문에 기존 역직렬화가 구성된 클래스에서
클래스 버전이 일치하지 않다는 에러문구가 뜨게 됩니다.
이유는 SerialVersionUID 의 값을 생성해 내는 계산은 클래스의 세부사항에 매우 민감하게 반응하기 때문에
컴파일러 구현체에 따라서 달라질 수 있어서 역직렬화 과정에서 예상하지 못한 InvalidClassException 에러를 유발할 수 있습니다.
이것은 클래스의 이름이 똑같다고 하더라도 클래스 버전이 달라지는 경우가 발생합니다.
하지만 만약 여기서, static 변수나 transient 키워드가 붙은 인스턴스변수는 직렬화에 영향을 끼치지 않기 때문에
클래스의 버전을 다르게 인식하도록 할 필요가 없습니다.
static 에 대해서는 보통 아실 테지만, transient 키워드는 직렬화 대상을 제외시키도록 하는 제어자입니다.
이 키워드가 어떨 때 쓰이는지는 밑에서 조금 더 자세히 설명하도록 하겠습니다.
SerialVersionUID 를 수동으로 설정하는 방법
자동으로 생성되는 경우가 아닌, 직접 사용자가 수동으로 설정하는 방법은 어떻게 해야 하는지 간단하게 설명해 보겠습니다.
SerialVersionUID 의 값은 정수값이면 어떠한 값으로도 지정할 수 있지만, 서로 다른 클래스 간에 같은 값을 갖지 않도록
serialver.exe 를 사용해서 생성된 값을 사용하는 것이 보통이라고 합니다.
그래서 serialver.exe 뒤에 SerialVersionUID 를 얻고자 하는 클래스 이름만 적어주면
클래스의 SerialVersionUID 를 얻어낼 수 있게 됩니다.
그러나, 이클립스 3.3 이후부터는 serialver.exe 로 생성되는 값을 자동으로 생성해 주는 방식이 생겼는데
사진으로 설명드리겠습니다.
먼저 직렬화가 구현되어있는 클래스에서 노란색 경고표시가 뜨고 있는 것을 확인할 수 있습니다.
이때 빨간색이 아닌 노란색인 이유는 SerialVersionUID의 값이 자동으로 생성되기는 하나, 수동으로 선언하는 것을 권장하기 때문에
이클립스 쪽에서는 노란색으로 경고표시를 띄우는 것입니다.
그러면 저 노란색 밑줄이 그어진 Person 위에 마우스를 올리면 SerialVersionUID 값을 생성할 수 있는데
default 는 기본값이므로 1L 를 생성해 주기 때문에, 그 아래의 generated SerialVersionUID 값을 눌러줘야 합니다
누르게 되면 이와 같이 SerialVersionUID 값이 생성되는 것을 확인할 수 있습니다.
transient 란?
아까 설명드리기로 한 transient 제어자에 대해서 짚고 넘어가보겠습니다.
간단하게 위에서도 언급했었지만, 제어자 transient 를 인스턴스 변수 앞에 붙이게 되면, 직렬화 대상에서 제외할 수 있게 됩니다.
즉, 클래스 내용안에 직렬화가 안 되는 객체에 대한 참조를 포함하고 있다면 transient 키워드를 붙여서 제외할 수 있습니다.
보통 Object obj = new Object(); 의 경우 직렬화를 할 때 에러가 발생하면서 실패하는데
그 이유는 모든 객체의 최고 조상인 Object 클래스에는 Serializable 인터페이스가 구현되어있지 않기 때문입니다.
이럴 때 직렬화 하려는 클래스 내부에 해당 인스턴스 변수가 존재할 경우 아래 코드와 같이 앞에 붙여주면 직렬화 대상에서 제외됩니다.
코드로 살펴보자면,
class Person implements java.io.Serializable {
String name;
int age;
transient Object obj = new Object();
}
이렇게 간단하게 붙여주면 끝납니다!
추가적으로 만약 Object obj = new String(”abc”); 로 하게 될 경우에는 직렬화가 가능해집니다.
저장된 객체가 Object 가 아닌 String 인스턴스이기 때문이에요.
인스턴스변수의 타입이 아닌 실제로 연결된 객체의 종류에 의해서 결정된다는 것을 기억해 두면 좋을 것 같습니다.
마무리
오늘도 끝까지 봐주신 분들께 감사드립니다.
이번 이 주제는 남궁 성 선생님의 Java 의 정석 책으로 공부하고 참고하였습니다.
'Computer Science > Java' 카테고리의 다른 글
Array, LinkedList, ArrayList의 차이점 (2) | 2023.10.24 |
---|---|
Reflection(리플렉션) 에 대한 개념 및 단점, 그럼에도 쓰는 이유 (2) | 2023.10.10 |
String, StringBuffer, StringBuilder의 차이 (2) | 2023.09.21 |