CHANGEL
SOLID BASICS
CHANGEL

공지사항

  • DEV.CHANGEL PROFILE
  • SOLID BASIC (289)
    • 공부 STUDY (115)
      • JAVA (57)
      • C | C++ (34)
      • CS (11)
      • MySQL (2)
      • ALGORITHM (1)
      • HTML (2)
      • CSS (2)
      • JS (2)
      • CODING (0)
      • MINI PROJECT (3)
    • 스프링 SPRING (21)
      • [SPRING] 김영한 스프링 입문 (11)
      • [SPRING] 남궁성 스프링의 정석 (1)
      • [SPRING] 스프링 핵심원리 (9)
    • 전공 수업 CS (65)
      • Computer Network (13)
      • algorithms (21)
      • Computer Architecture (7)
      • Software Engineering (4)
      • Data Structure (2)
      • DataBase (1)
      • Digital Engineering (14)
      • Discrete Mathematics (3)
      • Introduction to programming (0)
      • Mobile Software (0)
      • Intelligence and Informatio.. (0)
    • 대외활동 (35)
      • 신한은행 대학생 홍보대사 34기 (8)
      • SKT T프렌즈 5기 (13)
      • SK DEVOTION YOUNG 1기 (9)
      • 성균관 대학교 공학교육혁신센터 수강 (3)
      • 수상 기록 (1)
    • 솝트 33기 안드로이드 (7)
      • [솝트 33기] 회고록 (0)
      • [솝트 33기] 안드로이드 왕초보 스터디 (2)
      • [솝트 33기] 코틀린 스터디 (0)
      • [솝트 33기] Git을 털어보자 깃털 스터디 (4)
    • 멋쟁이사자처럼 11기 (6)
      • 멋사 회고록 (4)
      • 백엔드 세션 (1)
      • 기획 세션 (1)
      • 연합해커톤 운영단 (기획팀) (0)
    • 백준 BAEKJOON (16)
    • 독서 BOOK (10)
    • 자격증 CERTIFICATE (1)
    • 준비 서류 및 회고록 MEMOIR (7)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

최근 댓글

인기 글

CHANGEL

SOLID BASICS

공부 STUDY/JAVA

[JAVA] 직렬화 (Serialization ), 역직렬화 (Deserialization)

2023. 1. 24. 11:52

클래스의 인스턴스가 생성되면 인스턴스의 상태/ 인스턴스 변수 값은 마치 생명체처럼 계속 변하게 된다.

인스턴스의 어느 순간 상태를 그대로 저장하거나 네트워크를 통해 전송할 일이 있을 수 있다.

 

이것을 '직렬화' (Serialization)라고 한다.

그리고 저장된 내용이나 전송받은 내용을 다시 복원하는 것을 '역직렬화' (Deserialization)라고 한다. 

다시 말해서 직렬화란 인스턴스의 내용을 연속 스트림으로 만드는 것이다.

스트림으로 만들어야 파일에 쓸 수 있고 네트워크로 전송할 수도 있다. 따라서 직렬화 과정에서 하는 일은 인스턴스 변수 값을 스트림으로 만드는 것이다. 자바에서는 이를 보조 스트림인 ObjectInputStream과 ObjectOutputStream을 사용하여 좀 더 쉽게 구현할 수 있다.

 

Serialization 직렬화 -

인스턴스의 어느 순간 상태를 그대로 저장하거나 네트워크를 통해 전송하는 것

  • 클래스의 인스턴스가 생성되면 인스턴스의 상태, 즉 인스턴스 변수 값은 계속 변화함
  • 직렬화로 인스턴스 내용을 연속 스트림으로 만듬
  • 스트림으로 만들어야 파일에 쓰거나 네트워크로 전송 가능
  • 직렬화 하고자 하는 클래스에서 반드시 Serializable 인터페이스를 구현해야 함
  • 직렬화시 모든 유형의 객체를 저장해야 하기 때문에 Object 클래스형으로 저장됨

 

Deserialization 역직렬화-

 

저장된 내용이나 전송받은 내용을 다시 복원하는 것

  • 역직렬화를 할 때 클래스 정보가 존재하지 않을 수도 있으므로
    ClassNotFoundException 예외도 처리해야함
  • Object 클래스형으로 읽어 들인 객체를
    저장할 클래스 자료형에 맞게 형 변환(Downcasting) 해야 함

ObjectInput / OutputStream

-직렬화를 도와주는 자바의 보조 스트림

ObjectInputStream(InputStream in) InputStream을 매개변수로 받아 ObjectInputStream 생성
ObjectOutputStream(OutputStream out) OutputStream을 매개변수로 받아 ObjectOutputStream 생성

 

저장할 파일이나 전송할 네트워크 등의 기반 스트림을 매개변수로 받아서 인스턴스 변수 값을 저장하거나 전송한다.

Object readObject() ObjectInputStream 클래스 일반 메소드
객체 데이터를 스트림으로 불러올 때 사용
void writeObject(Object obj) ObjectOutputStream 클래스 일반 메소드
객체 데이터를 외부로 전송할 때 사용

 

 


직렬화를 테스트 해보자.

Person 클래스를 하나 만들고 인스턴스로 생성한 후 파일에 썼다가 복원하는 예제를 보자.

 

먼저 Person클래스의 생성자로 두 인스턴스를 생성한 후 이를 serial.out 파일에 저장하고 - 직렬화

serial.out 파일에서 저장된 내용을 읽어 원래 인스턴스 상태로 복원해보자 - 역직렬화

 

package stream.serialization;

public class Person {
    private static final long serialVersionUID = -1923204802334L; 
    String name;
    String job;
    
    public Person() {}
    
    public Person(String name, String job) {
        this.name = name;
        this.job = job;
    }
    
    public String toString() {
        return name + "," + job;
    }
}
class Person implements Serializable{
	
	private static final long serialVersionUID = -1503252402544036183L;

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

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

public class SerializationTest {

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

		Person personAhn = new Person("안재용", "대표이사");
		Person personKim = new Person("김철수", "상무이사");
		
		try(FileOutputStream fos = new FileOutputStream("serial.out");
				ObjectOutputStream oos = new ObjectOutputStream(fos)){
			
			oos.writeObject(personAhn); // 인스턴스 값을 파일에 씀 - 직렬화
			oos.writeObject(personKim);
		
		}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();
		}
	}
}

 

serial.out 파일을 열어보면 날아볼 수 없는 내용들이 써있다. 참고로 역질렬화를 할 떄는 클래스의 정보가 존재하지 않을 수 있기에 ClassNotFoundException도 처리해야한다.

 

그런데 프로그램을 실행하면 오류가 생긴다.

직렬화는 인스턴스의 내용이 외부로 유출되는 것이기에 프로그래머가 직렬화를 하겠다는 의도를 표시해야한다. 

따라서 Person 클래스에 마커 인터페이스인 Serializable 인터페이스를 추가해야한다.


Serializable 인터페이스

- 직렬화는 인스턴스 내용이 외부로 유출되는 것이므로 프로그래머가 직렬화를 하겠다는 의도를 표시해야 하는데, 이 때 구현해야 하는 인터페이스

  • Marker Interface (마커 인터페이스)
    다른 기능은 없고 해당 클래스를 직렬화하겠다는 의사만 명시하는 인터페이스
  • 추상 메소드가 없는 인터페이스
    오버라이딩을 하지 않아도 됨(할 수 없음)

형식

class Person implements Serializable {
   
}

transient 예약어

- 직렬화 / 역직렬화 과정에서 제외하고자 하는 변수 앞에 작성하는 예약어

 

사전적 의미: '일시적인, 일시적으로 머무르는'

  • 직렬화 될 수 없는 클래스(ex. Socket)가 인스턴스 변수로 있는 경우에 사용
  • 직렬화를 원치 않는 변수에 사용
  • transient 예약어를 사용한 변수에는 그 자료형의 기본 값이 저장됨
    ex) 객체 자료형의 경우 null 값이 저장됨

직렬화의 대상이 되는 클래스는 모든 인스턴스 변수가 직렬화되고 복원된다. 그렇기에 어떤 변수를 특정하여 직렬화를 하지 않으려면 이 예약어를 사용하면 된다. 그러면 해당 변수는 직렬화되고 복원되는 과정에서 제외된다. 이 예약어를 사용한 변수 정보는 그 자료형의 기본값으로 저장된다. 따라서 객체 자료형인 경우 null 값이 된다.

 

// 역직렬화 할때와 직렬화를 했었을 때의 상태가 다르면 오류가 발생한다. 내용이 변경된 경우이다. 이러한 경우 클래스의 버전관리를 개발자가 할 수 있다.

 

Externalizable 인터페이스

직렬화를 하는 데 사용하는 인터페이스. 프로그래머가 구현해야하는 메서드가 있다. 객체의 직렬화와 역직렬화를 직접 세밀하게 제어하고자 할 때 메서드에 내용을 구현한다. 

 

package stream.serialization;

import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

class Dog implements Externalizable{

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

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

public class ExternalizableTest {

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

		Dog myDog = new Dog();
		myDog.name = "멍멍이";
		
		
		FileOutputStream fos = new FileOutputStream("external.out");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		try(fos; oos){
			oos.writeObject(myDog);
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		
		FileInputStream fis = new FileInputStream("external.out");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		Dog dog = (Dog)ois.readObject();
		
		System.out.println(dog);
	}
}

 

여기서 읽고 쓰는 내용을 프로그래머가 구현해야한다.

'공부 STUDY > JAVA' 카테고리의 다른 글

[JAVA] Assertions.assertThat 비교 하기  (0) 2023.01.25
[JAVA] File 클래스 | RandomAccessFile 클래스에 대해 알아보자  (0) 2023.01.24
[JAVA] 보조 스트림(Wrapper 스트림)에 대해 알아보자 |FIilterInputStream, FilterOutputStream  (0) 2023.01.24
[JAVA] 자바 입출력과 스트림 - (4) | 문자 단위 스트림  (0) 2023.01.24
[JAVA] 자바 입출력과 스트림 - (3) | 바이트 단위 스트림 - OutputStream  (0) 2023.01.24
    '공부 STUDY/JAVA' 카테고리의 다른 글
    • [JAVA] Assertions.assertThat 비교 하기
    • [JAVA] File 클래스 | RandomAccessFile 클래스에 대해 알아보자
    • [JAVA] 보조 스트림(Wrapper 스트림)에 대해 알아보자 |FIilterInputStream, FilterOutputStream
    • [JAVA] 자바 입출력과 스트림 - (4) | 문자 단위 스트림
    CHANGEL
    CHANGEL
    NOT GIVING UP | SOLID BASICS

    티스토리툴바