본문 바로가기

언어공부/Java

자바 - 직렬화(serialization), ObjectInputStream&ObjectOutputStream

자바 직렬화(serialization)에 대해서 알아보자.

직렬화(serialization)

직렬화란 객체를 데이터 스트림으로 만드는 것을 뜻한다. 객체에 저장된 데이터를 스트림에 쓰기(write)위해 연속적인 데이터로 변환하는것을 말한다. 반대로 스트림으로 부터 데이터를 읽어서 객체를 만드는 것을 역직렬화(deserialization)라고 한다.

 

객체는 클래스에 정의된 인스턴스 변수의 집합이다. 그래서 객체를 저장한다는 것은 객체의 모든 인스턴스 변수의 값을 저장한다는 것과 같은 의미이다. 또한 데이터들이 개별적으로 전송되는 것이 아니고 클래스 내부에 설계된 멤버들이 객체 단위로 파일에 기록하거나 쓴다는 의미이다. 객체를 저장하거나 전송하려면 직렬화가 필요하다.

 

ObjectInputStream&ObjectOutputStream

직렬화(스트림에 객체를 출력)에는 ObjecOutputStream을 사용하고, 역직렬화(스트림으로 부터 객체를 입력)에는 ObjectInputStream을 사용한다. ObjectInputStream&ObjectOutputStream는 각각 InputStream&OutputStream을 직접 상속받지만 기반 스트림을 필요로 하는 보조스트림이다. 그래서 객체를 생성할 때 입출력(직렬화/역직렬화)할 스트림을 지정해 주어야 한다.

ex) ObjectInputStream(InputStream in) / ObjectOutputStream(OutputStream out)

 

파일에 객체를 저장(직렬화)하고 싶다면 다음과 같이 하면 된다.

ex) FileOutputStream fos=new FileOutputStream("objectfile.ser");

ObjectOutputStream out=new ObjectOutputStream(fos);

out.writeObject(new UserInfo());

 

objectfile.ser라는 파일에 UserInfo객체를 직렬화해 저장한다. 출력할 스트림(FileOutputStream)을 생성해서 이를 기반스트림으로 하는 ObjectOutputStream을 생성한다. ObjectOutputStream의 writeObject(Object obj)를 사용해서 객체를 출력하면, 객체가 파일에 직렬화되어 저장된다.

 

역직렬화 방법은 직렬화할 때와는 달리 입력스트림을 사용하고 writeObject대신 readObject를 사용해 저장된 데이터를 읽기만 하면 객체로 역직렬화 된다. 다만 readObject()의 반환타입이 Object이기 때문에 객체 원래의 타입으로 형변환 해주어야한다.

 

직렬화가 가능한 클래스 만들기

직렬화가 가능한 클래스를 만드는 방법은 간단한데, 직렬화하고자 하는 클래스가 java.io.Serializable인터페이스를 구현하도록 하면 된다. Serializable을 구현한 클래스를 상속받는다면, Serializable을 구현하지 않아도 된다. 조상클래스에서 구현했기 때문에 자손클래스에서도 직렬화가 가능하다.

 

ex)

 

해당 코드에서는 Externalizable을 구현한 클래스 Customer를 만들었다. 제한된 직렬화를 원하거나 객체의 일부를 직렬화하지 않으려면 Externalizable을 사용한다. Externalizable 인터페이스는 Serializable 인터페이스를 확장하고 writeExternal() 및 readExternal()의 두 가지 메소드를 추가했다. 추가로 Externalizable로 구현하면 기본 생성자는 public이어야하며 그렇지 않으면 코드에서 예외가 발생한다.

 

ex) 

 

출력화면

 

iotest.txt

해당 cus객체가 파일에 직렬화 되어 저장된다.

 

ex)

 

출력화면

 

cus에 객체단위로 읽어온 것을 저장해 출력한다. 여기서 readObject()의 봔한타입이 Object이기 때문에 객체 원래의 타입으로 형변환을 해준다.