87. 커스텀 직렬화 형태를 고려해보라
0. 시작 하기 전, Serializable 핵심 요약
Serializable 핵심 요약%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#f0f8ff', 'primaryTextColor': '#000', 'primaryBorderColor': '#7570b3', 'lineColor': '#333', 'edgeLabelBackground':'#fff', 'clusterBkg': '#fcfcfc'}}}%%
graph LR
subgraph 실행 과정
O[MyClass 객체] -- 직렬화 (객체 -> 바이트) --> BYTES[바이트 스트림];
BYTES -- 저장 --> Storage[(파일/DB)];
BYTES -- 전송 --> Network((네트워크));
Storage -- 로딩 --> BYTES_IN[바이트 스트림];
Network -- 수신 --> BYTES_IN;
BYTES_IN -- 역직렬화 (바이트 -> 객체) --> O2[MyClass 객체 복원];
end
subgraph 클래스 정의
A[MyClass] -- 구현 --> B(Serializable);
end
style B fill:#ccf,stroke:#333,stroke-width:2px핵심 포인트
1. 왜 기본 직렬화는 위험할 수 있는가? 🤔
핵심 문제: 기본 직렬화는 객체의 논리적 데이터가 아닌, 물리적 표현을 그대로 저장.
발생 가능한 문제점들
1. API 고착화
2. 성능 저하 (공간)
3. 성능 저하 (시간)
4. StackOverflowError 위험
5. 정확성 문제
기억하세요
2. 그렇다면, 언제 기본 직렬화를 써도 괜찮을까? ✅
황금률: 객체의 논리적 내용과 물리적 표현(필드) 이 거의 동일할 때만 사용을 고려합니다.
주의: 기본 직렬화가 적합해 보여도, 역직렬화 시 데이터 유효성 검사나 불변식 보장을 위해 readObject 메서드가 필요할 수 있습니다.
readObject 메서드가 필요할 수 있습니다.3. 해결책: 커스텀 직렬화 (writeObject/readObject) 💡
목표: 객체의 논리적인 데이터만 효율적으로 저장하고 복원
핵심 도구:
transient 키워드:
transient 키워드:private void writeObject(ObjectOutputStream out) throws IOException;
private void writeObject(ObjectOutputStream out) throws IOException;private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;개념 예시 (StringList):
장점: 유연성 확보, 성능(공간/시간) 향상, 안정성 증가(스택 오버플로 방지)
4. 직렬화 시 반드시 지켜야 할 것들! 📌
1. serialVersionUID를 명시적으로 선언하세요!
serialVersionUID를 명시적으로 선언하세요!왜?
어떻게?
언제 변경?
2. transient 필드 초기화를 신경 쓰세요.
transient 필드 초기화를 신경 쓰세요.3. 동기화를 고려하세요.
4. 직렬화 형태를 문서화하세요.
5. 핵심 정리 ✨
Last updated