직렬화(Serialization)

김종하·2020년 10월 18일
1

DiveIntoJAVA

목록 보기
4/11
post-thumbnail

직렬화?

https://en.wikipedia.org/wiki/Serialization
In computing, serialization (US spelling) or serialisation (UK spelling) is the process of translating a data structure or object state into a format that can be stored (for example, in a file or memory data buffer) or transmitted (for example, across a computer network) and reconstructed later (possibly in a different computer environment).

위키피디아에서, 직렬화에 대한 설명을 찾아보면 위와 같이 설명하는데 번역하자면 serialization 은 데이터 구조나 객체를 저장(파일이나 memory data buffer) 하기 위한 형태(format) 혹은 전달가능한 형태로(네트워크를 통한)바꾸는 과정을 뜻한다. 그리고 직렬화된 데이터 format은 추후에 다른 컴퓨터 환경에서도 다시 본래의 데이터 구조나 객체로 재조립 될 수 있다. 정도로 의역할 수 있다.

조금 더 쉽게 설명하자면 자바 프로그램에서 데이터를 저장하거나 전송할 때 스트림 형태로 저장하고 전송하게 되는데, 객체를 스트림형태로 만드는 과정을 '직렬화' 라고 할 수 있겠다.

그럼 왜 스트림 형태로 만드는걸까라는 의문이 들 수 있을텐데 어쨋든 컴퓨터는 이진수 체계를 따르니, 객체를 객체 그대로 전달할 수 없는 문제가 있다. 1과 0으로 객체를 표현하기 위해서는 약속이 필요할 것이고, 그 약속을 스트림이라고 생각하고 넘어가자. (확실한 정보는 아니고, 개인적인 생각입니다... 틀린 부분이 있다면 말씀해주세요 ! )

직렬화 활용

그렇다면 어떻게 직렬화를 활용할 수 있는지 코드를 통해 알아보자

public class ObjectOutPutExample {
    public static void main(String[] args) throws FileNotFoundException {
        try(
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("outputExample.dat"));
                )
        {
            out.writeObject(new GregorianCalendar(2020,10,18));
            out.writeObject(new GregorianCalendar(2020,10,19));
            out.writeObject(new GregorianCalendar(2020,10,20));
        } catch (IOException ioe){
            ioe.printStackTrace();
        }
    }
}

(참고 : Java 8 부터 지원하는 try-with-resource 문을 통해 자동으로 자원을 해제하였다)
ObjectOutputStream 의 writeObject() 메소드는 파라미터로 넘겨준 객체를 스트림으로 만들어 출력하는 메소드이다. 여기서, 근데 중요한 것은 바로 GregorianCalendar 클래스는 직렬화가 가능한 클래스란 점이다. 그렇다면 직렬화가 가능한 클래스는 어떻게 만들 수 있는 것일까?
한번 살펴보도록 하자.
GregorianCalendar 는

public class GregorianCalendar extends Calendar {}

Calendar 를 상속받은 클래스 였다. 그렇다면 Calendar 로 가보자.

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {}

Calendar 는 추상클래스인데 살펴보면 Serializable 이란 interface 를 구현하고 있다. 바로 이 Serializable 을 구현한 클래스들이 직렬화가 가능한 클래스이다.
아주 간단하게 Serializable 인터페이스를 구현하기만 하면 해당 클래스는 직렬화가 가능해지는 것이다.
그렇다면 Serializable 을 구현하지 않고 스트림으로 넣어 출력하려면 어떻게 될까?

간단하게 Person 이란 클래스를 만들어 보았다.

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

그리고 앞서했던 방법과 같은 방법으로 스트림을 출력하려해보았다.

public class ObjectOutputExample2 {
    public static void main(String[] args) throws FileNotFoundException {
        try(
                ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("outputExample2.dat"));
        )
        {
            out.writeObject(new Person("jaden", 10));
        } catch (IOException ioe){
            ioe.printStackTrace();
        }
    }
}

그러자, 당연스럽게도 에러가 떨어졌는데 해당 에러는 바로

java.io.NotSerializableException: serialization.Person

다음과 같았다. 해결하기 위해서 밑에와 같이 Person 클래스에서 Serializable 인터페이스를 구현했더니, 에러없이 잘 수행되었다.

public class Person implements Serializable{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

역직렬화?

객체를 직렬화하여 stream 형태로 바꾸었다면, 다시 객체 형태로 바꾸는 작업 역시 필요하다. 이를 바로 역직렬화 라고 하는 것이다.

[도움을 얻은 곳]

0개의 댓글