티스토리 뷰
개념
자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 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
- woowabros.github.io/experience/2017/10/17/java-serialize.html
- woowabros.github.io/experience/2017/10/17/java-serialize2.html
- nesoy.github.io/articles/2018-04/Java-Serialize
- flowarc.tistory.com/entry/Java-%EA%B0%9D%EC%B2%B4-%EC%A7%81%EB%A0%AC%ED%99%94Serialization-%EC%99%80-%EC%97%AD%EC%A7%81%EB%A0%AC%ED%99%94Deserialization
'프로그래밍 언어 > Java Programming' 카테고리의 다른 글
JDBC객체 및 DB 연결 (0) | 2016.12.24 |
---|---|
JAVA 실행시간 측정 방법 (0) | 2016.11.19 |
Java FilterStream feat. BufferedStream (0) | 2016.10.22 |
Java PipedInputOutputStream 클래스 (0) | 2016.10.22 |
JAVA ByteArrayInputStream 클래스 (0) | 2016.10.22 |
댓글