반응형
이 포스팅에서 작성하는 내용은 EFFECTIVE JAVA(이펙티브자바) 에서 발췌하였습니다.
아이템 86. Serializable을 구현할지는 신중히 결정하라
- 어떤 클래스의 인스턴스를 직렬화할 수 있게 하려면 클래스 선언에 implements Serializable만 덧붙이면 된다.
- Serializable을 구현하면 릴리스한 뒤에는 수정하기 어렵다.
- 클래스가 Serializable을 구현하면 직렬화된 바이트 스트림 인코딩도 하나의 공개 API가 되며, 이 클래스가 널리 퍼지는 경우 그 직렬화 형태도 영원히 지원해야 한다.
- 커스텀 직렬화 형태를 설계하지 않고 자바의 기본 방식을 사용하면 직렬화 형태는 최소 적용 당시 클래스의 내부 구현 방식에 묶인다.
- 즉, 기본 직렬화 형태에서는 클래스의 private과 package-private 인스턴스 필드들마저 API로 공개된다.
(은닉, 캡슐화 X) - 직렬화 가능 클래스를 만드고자 한다면, 길게 감당할 수 있을 만큼 고품질의 직렬화 형태도 주의해서 함께 설계해야 한다.
직렬화의 단점
- 직렬화는 클래스 개선을 방해할 수 있다.
- ex) 스트림 공유 식별자(serial version UID)
- 모든 직렬화된 클래스는 고유 식별 번호를 부여받는데, 이 값을 생성하는 데는 클래스 이름, 구현한 인터페이스들, 컴파일러가 자동으로 생성하는 것을 포함한 대부분의 클래스 멤버들이 고려된다.
- 그 결과, 나중에 편의 메서드를 추가하는 식으로 이들 중 하나라도 수정한다면 직렬 버전 UID 값도 변한다.
- 버그와 보안 구멍이 생길 위험이 높아진다.
- 객체는 생성자를 사용해 만드는 게 기본인데, 직렬화는 언어 기본 메커니즘을 우회하는 객체 생성 기법이다.
- 기본 방싣을 따르든 재정의해 사용하든 역직렬화는 일반 생성자의 문제가 그대로 적용되는 '숨은 생성자'다.
- 이 숨은 생성자. 즉, 역직렬화를 사용하면 불변식 깨짐과 허가되지 않은 접근에 쉽게 노출된다.
- 해당 클래스의 신버전을 릴리스할 때 테스트할 것이 늘어난다.
- 직렬화 가능 클래스가 수정되면 신버전 인스턴스를 직렬화한 후 구버전으로 역직렬화할 수 있는지, 반대도 가능한 지 검사해야 한다.
위와 같이, Serializable 구현 여부는 가볍게 결정할 사안이 아니다.
- 단, 객체를 전송하거나 저장할 때 자바 직렬화를 이용하는 프레임워크용으로 만든 클래스라면 선택의 여지가 없다.
- Serializable을 반드시 구현해야 하는 다른 클래스의 컴포넌트로 쓰일 클래스도 마찬가지다.
- 역사적으로 BigInteger와 Instant 같은 '값' 클래스와 컬렉션 클래스들은 Serializable을 구현하고, 스레드 풀처럼 동작하는 객체를 표현한 클래스들은 대부분 Serializable을 구현하지 않았다.
직렬화 유의점
- 상속용으로 설계된 클래스는 대부분 Serializable을 구현하면 안 되며, 인터페이스도 대부분 Serializable을 확장해서는 안 된다.
- Serializable을 구현하지 않기로 할 때는 한 가지만 주의하면 된다.
- 상속용 클래스인데 직렬화를 지원하지 않으면 그 하위 클래스에서 직렬화를 지원하려 할 때 부담이 늘어난다.
- 하위 클래스에서는 어쩔 수 없이 직렬화 프록시 패턴[아이템 90]을 사용해야 한다.
- 내부 클래스는 직렬화를 구현하지 말아야 한다.
- 내부 클래스에 대한 기본 직렬화 형태는 분명하지 않다.
정리
- Serializable은 구현한다고 선언하기는 아주 쉽지만, 그것은 눈속임일 뿐이다.
- 한 클래스의 여러 버전이 상호작용할 일이 없고 서버가 신뢰할 수 없는 데이터에 노출될 가능성이 없는 등, 보호된 환경에서만 쓰일 클래스가 아니라면 Serializable 구현은 아주 신중히 이뤄져야 한다.
- 상속할 수 있는 클래스라면 더욱 주의해야한다.
반응형
'BE > Java' 카테고리의 다른 글
[Effective Java] 아이템 88. readObject 메서드는 방어적으로 작성하라 (0) | 2023.01.03 |
---|---|
[Effective Java] 아이템 87. 커스텀 직렬화 형태를 고려해보라 (1) | 2023.01.02 |
[Effective Java] 아이템 85. 자바 직렬화의 대안을 찾으라 (0) | 2022.12.28 |
[Effective Java] 아이템 84. 프로그램의 동작을 스레드 스케줄러에 기대지 말라 (1) | 2022.12.27 |
[Effective Java] 아이템 83. 지연 초기화는 신중히 사용하라 (0) | 2022.12.26 |