Java 직렬화 (Serialization)

Codren·2021년 6월 6일
0

입출력 스트림

목록 보기
4/4

Section 1. 직렬화

1. 직렬화 (Serialization)

객체(인스턴스)를 기록할 수 있는 포맷으로 변환하여 파일로 저장하거나 다른 시스템과 송수신 가능하게 하는 기법

  • 즉, 객체 또는 객체의 상태를 쉽게 옮길 수 있는 형태로 변환하는 과정
  • 직렬화 / 역직렬화(Deserialization) 존재




2. 직렬화의 종류

    ① 바이너리 직렬화 - 객체를 byte 형태(스트림 형태)로 변환하여 원래 상태를 그대로 보존 (= java 직렬화)
    ② Json 직렬화 - 객체의 상태를 key-value 형태로 변환하여 시스템 간 송수신
    ③ XML 직렬화 - 공용 프로퍼티와 공용 필드만 직렬화




3. Java 직렬화 (Serialization)

  • 바이너리 직렬화
  • 자바에서는 보조 스트림을 활용하여 직렬화를 제공함
생성자설명
ObjectInputStream(InputStream in)InputStream을 생성자의 매개변수로 받아 ObjectInputStream을 생성
OObjectOutputStream(OutputStream out)OutputStream을 생성자의 매개변수로 받아 ObjectOutputStream을 생성




4. Serializable 인터페이스

  • 직렬화는 인스턴스의 내용이 외부로 유출되는 것이므로 직렬화 대상 객체에 의도를 표시
  • 구현 코드가 없는 marker interface
  • transient - 직렬화 하지 않으려는 멤버 변수에 사용함 (Socket등 직렬화 할 수 없는 객체)




5. 자바 직렬화 구현

  • 직렬화 대상이 되는 Person 클래스 정의
class Person implements Serializable{
	
	private static final long serialVersionUID = -1503252402544036183L;

	String name;
	String job;
	
	public Person() {}

	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString()
	{
		return name + "," + job;
	}
}
  • FileInputStream, FileOutputStream 기반 스트림을 ObjectStream 으로 묶음
public class SerializationTest {

	public static void main(String[] args) throws ClassNotFoundException {

		Person personLee = new Person("이순신", "대표이사");
		Person personKim = new Person("김유신", "상무이사");
		
		try(FileOutputStream fos = new FileOutputStream("serial.out");
				ObjectOutputStream oos = new ObjectOutputStream(fos)){
			
			oos.writeObject(personLee);		# 직렬화하여 write
			oos.writeObject(personKim);		# 직렬화하여 write
		
		}catch(IOException e) {
			e.printStackTrace();
		}
			
		try(FileInputStream fis = new FileInputStream("serial.out");
			ObjectInputStream ois = new ObjectInputStream(fis)){
			
			Person p1 = (Person)ois.readObject();	# 직렬화된 바이트 데이터 객체화 (역직렬화)
			Person p2 = (Person)ois.readObject();	# 직렬화된 바이트 데이터 객체화 (역직렬화)
			
			System.out.println(p1);
			System.out.println(p2);
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}



Section 2. Externalizable 인터페이스

1. Externalizable 인터페이스

  • 객체가 어떻게 변환될지 프로그래머가 직접 코드를 구현할 수 있음
  • writerExternal 과 readExternal 메서드를 구현해야 함




2. Externalizable 인터페이스 구현

class Person implements Externalizable{
	
	String name;
	String job;
	
	public Person() {}

	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString()
	{
		return name + "," + job;
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(name);
		//out.writeUTF(job);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		name = in.readUTF();
		//job = in.readUTF();
	}
	
}




3. 동작 원리

  • 직렬화, 역직렬화 될 때 객체 자체가 그대로 변환됨
  • Externalizable 인터페이스는 변환 과정에서 멤버 변수의 값을 다른 값으로 변경 가능
  • 직렬화

    ① 객체를 출력하는 메소드가 호출 = oos.writeObject(personLee) 호출
    ② 객체의 클래스가 Externalizable 인터페이스를 구현했는지 확인
    ③ 만약 구현했다면 writeExternal() 메소드를 통해서 전송 데이터를 직렬화
    ④ Externalizable 인터페이스를 구현하지 않았다면 Serializable 구현한지 확인
    ⑤ 구현했다면 그대로 객체 스트림에 객체 전체를 직렬화
    ⑥ 둘 다 구현하지 않았으면 Exception


  • 역직렬화

    ① Person p1 = (Person)ois.readObject() 호출
    ② 스트림을 통해 전송받은 객체가 Externalizable 인터페이스를 구현했는지 확인
    ③ 구현했다면 readExternal() 메소드를 통해서 전송받은 데이터를 순서대로 읽어 객체를 직렬화
    ④ 구현하지 않았다면 Serializable 인터페이스를 통해 객체 전체를 역직렬화

0개의 댓글