직렬화, 역직렬화
직렬화란, 객체를 데이터 스트림으로 만드는 것을 뜻한다. 이를 풀어서 말하면, 객체에 저장된 데이터(인스턴스 변수)를 연속적인 데이터로 변환하는 것을 말한다.
역직렬화란, 직렬화와 반대로 스트림으로부터 데이터를 읽어 객체를 만드는 것을 말한다.
직렬화, 역직렬화 방법
직렬화 - ObjectOutputStream 사용
역직렬화 - ObjectInputStream 사용
// 직렬화 FileOutputStream fos = new FileOutputStream("sample.txt"); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(new Sample()); // 역직렬화 FileInputStream fis = new FileInputStream("sample.txt"); ObjectInputStream in = new ObjectInputStream(fis); Sample sample = (Sample) in.readObject();
직렬화와 역직렬화 작업은 객체의 모든 인스턴스 변수가 참조하고 있는 모든 객체를 대상으로 이루어지기 때문에 매우 복잡하고 시간이 오래 걸린다. 따라서, 직렬화 시간을 단축하고자 한다면 직렬화하려는 객체의 클래스에 2개의 메서드를 직접 구현해주어야 한다.
private void writeObject(ObjectOutputStream out) throws IOException { // 직렬화 } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // 역직렬화 }
직렬화 클래스 만들기
직렬화하고자 하는 클래스가 Serializable 인터페이스를 구현하도록 하면 된다. Serializable 인터페이스를 보면 아무 내용이 없는 것을 확인할 수 있는데, 단지 직렬화가 가능하다는 것을 알려주기 위한 마킹 용도로 사용된다고 이해하면 된다.
조상클래스가 Serializable 인터페이스를 구현하지 않은 경우, 자손클래스를 직렬화하게 되면 조상클래스에 정의된 인스턴스 변수는 직렬화 대상에서 제외된다. 따라서, 조상클래스의 인스턴스 변수도 직렬화 대상에 포함하기 위해서는 1. 조상클래스가 Serializable 인터페이스를 구현하게 하거나 2. 자손클래스에서 조상클래스의 인스턴스 변수가 직렬화되도록 처리하는 코드를 추가해줘야 한다.
직렬화하려는 객체의 클래스에 직렬화 대상이 아닌 객체에 대한 참조를 포함하는 경우, 제어자 transient를 이용해 직렬화 대상에서 제외할 수 있다. transient 제어자가 붙은 인스턴스 변수 자체가 직렬화가 되지 않는 것이 아닌, 인스턴스 변수 타입의 기본 값으로 직렬화된다.
역직렬화 시 주의할 점이 있는데, 바로 직렬화와 같은 순서로 역직렬화를 진행해야 한다는 것이다.
// 직렬화 FileOutputStream fos = new FileOutputStream("sample.txt"); ObjectOutputStream out = new ObjectOutputStream(fos); Sample s1 = new Sample("sample1"); Sample s2 = new Sample("sample2"); out.writeObject(s1); out.writeObject(s2); // 역직렬화 FileInputStream fis = new FileInputStream("sample.txt"); ObjectInputStream in = new ObjectInputStream(fis); // 직렬화와 동일한 순서로 진행 Sample s1 = (Sample) in.readObject(); Sample s2 = (Sample) in.readObject();
만약 직렬화와 역직렬화를 해야하는 객체가 많은 경우에는 자바 컬렉션을 이용해 직렬화 하는 것이 좋다.
직렬화 클래스 버전 관리
직렬화된 객체를 역직렬화하기 위해서는 직렬화를 했을 때와 같은 클래스를 사용해야 한다. 만약 클래스의 내용이 변경된 경우 역직렬화를 진행하게 되면 java.io.InvalidClassException이 발생하게 된다.
객체가 직렬화 될 때, 클래스에 정의된 멤버 정보를 바탕으로 클래스의 버전 정보인 serialVersionUID를 자동으로 생성해서 포함한다. 역직렬화 시, 해당 정보를 통해 직렬화할 때의 클래스 버전과 일치하는 지 확인할 수 있다. 이를 수동으로 관리(클래스 내 상수로 등록)해주게 되면 클래스의 정보가 변경되더라도 자동생성된 값으로 변경되지 않게 된다.
참고: Java의 정석 (남궁 성 지음)
'Web > Java' 카테고리의 다른 글
Collections Framework (2) Iterator, ListIterator, Enumeration (0) | 2022.02.15 |
---|---|
Collections Framework (1) ArrayList, LinkedList (0) | 2022.02.08 |
Reflection (0) | 2022.01.25 |
Statement vs PreparedStatement (0) | 2021.10.11 |
GC (Garbage Collector) (0) | 2021.09.05 |
댓글