본문 바로가기

Backend/Java

[JAVA] 객체의 직렬화, ObjectOutputStream, ObjectInputStream

728x90

직렬화(Serialize) 란?

  • 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술.
  •  JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 같이 이야기합니다.
  •  직렬화를 통해 프로그램이 실행되는 동안 생성된 객체를 스트림을 이용해서 지속적으로 보관하거나 전송 할 수 잇다. 

역직렬화(Deserialize) 란?

  • byte로 변환된 Data를 원래대로 Object나 Data로 변환하는 기술을 역직렬화(Deserialize)라고 부릅니다.
  • 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태

직렬화 가능한 클래스를 만드는 방법. 

1) Serializable 인터페이스를 이용

//직렬화가 되어 있어야 파일에 읽고 쓸수 있는 클래스가 된다. 
public class Data implements Serializable {
	private int no;
	private String name;
	private String mail;
	public Data(int no, String name, String mail) {
		super();
		this.no = no;
		this.name = name;
		this.mail = mail;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getMail() {
		return mail;
	}
	public void setMail(String mail) {
		this.mail = mail;
	}
}

 

2) Externalizable 인터페이스를 이용

public class Data implements Externalizable {
	private int no;
	private String name;
	private String mail;
	
	public Data(int no, String name, String mail) {
		super();
		this.no = no;
		this.name = name;
		this.mail = mail;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getMail() {
		return mail;
	}
	public void setMail(String mail) {
		this.mail = mail;
	}
	@Override
	public void writeExternal(ObjectOutput out) throws IOException {

	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

	}

}

 

 Externalizable 인터페이스는 Serializable 인터페이스를 확장한 형태로 세부적인 필드를 직접 제어할 수 있다.

 

transient 키워드를 사용하여 특정 필드를 제외시키는 것도 가능하지만 좀 더 세부적인 작업이 필요할 때 이렇게 Externalizable 인터페이스를 사용할 수 있다. 이를 위해서 이 인터페이스는 Serializable 인터페이스를 확장하고 출력을 위한 writeExternal() 메소드와  입력을 위한 readExternal() 메소드를 사용한다. 

 

하지만 Serializable 에서 transient 키워드를 사용하는 것이 편리하기 때문에 대부분 Serializable 인터페이스를 사용한다. 


ObjectStream 이란?



- ObjectOutputStream 과 ObejctInputStream은 각각 객체를 직렬화, 역직렬화하는 메소드를 제공하는 스트림이다. 

 

- 객체 스트림은 프로그램 메모리상에 존재하는 객체를 직접 입출력해 줄 수 있는 스트림으로 현재 상태를 보존하기 위한 영속성을 지원할 수 있다.

 

- 자바에서 객체 안에 저장되어 있는 내용을 파일로 저장하거나 네트워크를 통하여 다른 곳으로 전송하려면 객체를 바이트 형태로 일일이 분해해야 한다. 이를 위하여 객체를 직접 입출력 할 수 있도록 해주는 객체 스트림이다.

 

즉 ObejctStream을 사용하기 위해서 객체가 직렬화(Serialization) 가 되어 있어야 한다는 것이다.

 

사용 예시)

 

1) ObjectOutputStreamEx.java

 

public class ObjectOutputStreamEx {
	public static void main(String[] args) {
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("c:\\iotest\\obj.txt"));
			Data data = new Data(1, "choi", "abc@naver.com");
			oos.writeObject(data);
			System.out.println("입력 완료");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (oos != null) {
					oos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

실행 결과

 

2) ObjectInputStreamEx.java

 

//역직렬화해서 파일에서 읽어오기
public class ObjectInputStreamEx {
	public static void main(String[] args) {
		ObjectInputStream ois = null;
		try {
			// 파일에 저장된 객체를 읽어들이기 위해 ObjectInputStream 객체 생성
			ois = new ObjectInputStream(new FileInputStream("c:\\iotest\\obj.txt"));

			// ObjectInputStream 은 스트림으로 부터 읽어들인 직렬화된 객체를 역직렬화해서 객체를 생성할 수 있다.
			// 역직렬화할때 필요한 클래스 파일을 찾지 못할 경우
			// ClassNotFoundException 을 발생시킴.
			Data data = (Data) ois.readObject();
			System.out.println("번호 : " + data.getNo());
			System.out.println("이름 : " + data.getName());
			System.out.println("메일 : " + data.getMail());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				if (ois != null) {
					ois.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

 

 

실행결과

 

Serizable 된 Data 객체를 obj.txt 파일에다가 ObjectOutputStream을 이용해 저장하고 ObjectInputStream을 사용해 역직렬화하여 Data객체를 복구 해오는 것을 볼 수 있습니다.

 

 

# 참고자료

 

 woowabros.github.io/experience/2017/10/17/java-serialize.html

 

자바 직렬화, 그것이 알고싶다. 훑어보기편 - 우아한형제들 기술 블로그

자바의 직렬화 기술에 대한 대한 이야기입니다. 간단한 질문과 답변 형태로 자바 직렬화에 대한 간단한 설명과 직접 프로젝트를 진행하면서 겪은 경험에 대해 이야기해보려 합니다.

woowabros.github.io

 

Java Object Serialization Specification: 1 - System Architecture

CONTENTS | PREV | NEXT Java Object Serialization Specification version 6.0 System Architecture CHAPTER 1 Topics: The ability to store and retrieve JavaTM objects is essential to building all but the most transient applications. The key to storing

docs.oracle.com

docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html

 

ObjectInputStream (Java Platform SE 7 )

Load the local class equivalent of the specified stream class description. Subclasses may implement this method to allow classes to be fetched from an alternate source. The corresponding method in ObjectOutputStream is annotateClass. This method will be in

docs.oracle.com

docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html

 

ObjectOutputStream (Java Platform SE 7 )

An ObjectOutputStream writes primitive data types and graphs of Java objects to an OutputStream. The objects can be read (reconstituted) using an ObjectInputStream. Persistent storage of objects can be accomplished by using a file for the stream. If the st

docs.oracle.com

 

728x90