티스토리 뷰

개념

자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 Byte 형태로 데이터를 변환하는 기술과 Byte로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)를 아울러서 이야기 합니다.

 

 

직렬화 하여 파일에 저장하기

직렬화 할 객체 Person

public class Person implements Serializable{
        String id;
        String pw;
        String name;
        transient String ignore = "ignore";

        public Person(){
            this("none","1234","Gosuljo");
        }

        public Person(String id, String password, String name){
            this.id = id;
            this.pw = password;
            this.name = name;
        }

        public String toString(){
            return id+", " + pw + ", "+name;
        }
}

transient

직렬화 할 때 보안상 또는 필요하지 않는 데이터를 제외하고 싶다면 transient 옵션을 줄 수 있습니다. 직렬화 대상에서 제외되며 null 값이 저장됩니다.

 

직렬화

직렬화(Serialize) 조건

  • java.io.Serializable interface를 implements 받아야 합니다.
  • 직렬화는 ObjectOutputStream을 통하여 할 수 있습니다.
public static void main(String[] args) throws IOException {
        String fname = "obj.ser";

        FileOutputStream fo = new FileOutputStream(fname);
        BufferedOutputStream bo = new BufferedOutputStream(fo);

        ObjectOutputStream out = new ObjectOutputStream(bo);

        Person p1 = new Person("idkim","1111","엘리자벳");
        Person p2 = new Person("idpak","4567","크리스탈");

        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);

        out.writeObject(list);
        out.writeObject(new Date());

        out.close();
        fo.close();
        bo.close();
        System.out.println("직렬화되었습니다.");
}
 

역직렬화

역직렬화 조건

  • 역직렬화 할 객체가 class path에 존재해야 하며 import 되어 있어야 합니다.
  • 자바 직렬화 대상 객체는 동일한 serialVersionUID를 가지고 있어야 합니다.
private static void deSerialize() throws IOException, ClassNotFoundException {
        FileInputStream fi = new FileInputStream(fname);
        BufferedInputStream bi = new BufferedInputStream(fi);


        ObjectInputStream oin = new ObjectInputStream(bi);

        List<Person> list = (ArrayList<Person>)oin.readObject();
        Date date = (Date)oin.readObject();

        System.out.println(list);
        System.out.println("객체가 저장된 시간 : " + date.toString());
        System.out.println("현재시간 : " + new Date().toString());

        oin.close();
        bi.close();
        fi.close();
}

 

 

 

사용되는 곳

  • 캐시(Cache) Encache, Redis, Memcached 등 요청시마다 DB또는 파일 자원을 참조하지만 데이터의 변동이 없는 경우 직렬화 하여 캐시로 사용하는 것이 리소스를 아끼는데 유리합니다.
  • 자바 RMI(Remote Method Invocation) 원격에 있는 JAVA Method를 사용하는 기술로 데이터를 직렬화 하여 전달 받기 때문에 사용됩니다.

 

조심해야 할 점

역직렬화시 class 변경 문제

직렬화 한 객체 Person class에 변화가 일어나면 안됩니다.

java.io.InvalidClassException 이 일어나며 serialVersionUID가 다르다는 에러를 보게됩니다.

serialVersionUID는 class의 구조를 기반으로 생성되며 직렬화 할 때 기록되어 역직렬화 할 class의 serialVersionUID와 비교하여 일치하지 않으면 역직렬화에 실패하게 됩니다.

 

해결방법

직접 serialVersionUID를 관리해주어 해결할 수 있습니다. 만약 class의 구조가 달라지면 역직렬화 할 수 없어야한다 라고 한다면 기존 방법으로 사용해도 괜찮습니다.

 

이외에도 serialVersionUID값이 동일하더라도 변수의 type이 변경된다면 역직렬화 할 수 없습니다.

 

 

정리

  • 특별한 경우가 아니라면 serialVersionUID는 직접 관리하는게 좋습니다.
  • serialVersionUID가 같더라도 type의 변경에는 엄격합니다.
  • 장기간 저장될 정보는 직렬화 사용을 지양해야 합니다. 대상 class가 언제 변경될 지 모르기 때문입니다.
  • 직접 컨트롤 가능한 이외의 클래스(SecurityContext 같은)의 사용은 지양해야 합니다.

 

 

Reference

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함