Skip to content

[아이템 87] 커스텀 직렬화 형태를 고려해보라 #94

@Ori-Gui

Description

@Ori-Gui

📌 [아이템 87] 커스텀 직렬화 형태를 고려해보라

✨ 핵심 내용

  • 기본 직렬화 형태는 신중히 사용해야 한다.
    • 기본 직렬화는 객체의 물리적 표현을 저장하므로, 내부 구현에 의존하게 되어 유지보수에 문제가 생긴다.
    • 변경 예정인 내부 구조가 직렬화 형태에 포함되면, 해당 구현에 영원히 발이 묶이게 된다.
  • 기본 직렬화는 객체의 논리적 상태와 물리적 상태가 같을 때에만 적합하다.
  • 불변식을 보장하고 보안 문제를 방지하기 위해 readObject() 메서드를 직접 정의해야 할 수 있다.
  • 직렬화 형태는 일종의 공개 API로 간주되므로, @serial@serialData 태그를 활용해 문서화가 필요하다.

✅ 예제 코드 - 기본 직렬화 형태에 적합한 클래스

public class Name implements Serializable {
    /**
     * 성. null이 아니어야 함.
     * @serial
     */
    private final String lastName;

    /**
     * 이름. null이 아니어야 함.
     * @serial
     */
    private final String firstName;

    /**
     * 중간이름. 중간이름이 없다면 null.
     * @serial
     */
    private final String middleName;
}

❌ 예제 코드 - 기본 직렬화에 부적절한 클래스

public final class StringList implements Serializable {
    private int size = 0;
    private Entry head = null;

    private static class Entry implements Serializable {
        String data;
        Entry next;
        Entry previous;
    }
}

✅ 개선된 커스텀 직렬화 코드

private void writeObject(ObjectOutputStream s) throws IOException {
    s.defaultWriteObject();
    s.writeInt(size);
    for (Entry e = head; e != null; e = e.next)
        s.writeObject(e.data);
}

private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
    s.defaultReadObject();
    int numElements = s.readInt();
    for (int i = 0; i < numElements; i++)
        add((String) s.readObject());
}

💡 새롭게 알게 된 점

  • transient 키워드는 단순히 직렬화 제외를 위한 도구가 아니라, 논리 상태와 무관한 필드를 구분하기 위한 의도적 신호다.

📚 정리

  • 기본 직렬화를 무조건 사용하지 말고, 논리적 표현과 물리적 표현의 일치 여부를 먼저 따져보자.
  • writeObject/readObject를 직접 구현해 커스텀 직렬화 형태를 설계하는 것이 장기적인 유지보수에 유리하다.
  • 직렬화는 한번 선택하면 바꾸기 어렵기 때문에, 직렬화 형태도 API 수준으로 진지하게 다뤄야 한다.
  • 실제 프로젝트에서는 설정 파일이나 캐시, 복잡한 객체 상태 저장 시, 커스텀 직렬화 형태를 도입해 버전 관리와 유연성을 확보할 수 있다.

📢 댓글로 각자의 학습 내용을 공유해주세요!

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions