가장 먼저 직렬화/역직렬화를 개념의 이해전에 왜 사용하는지를 알아야 한다.
기업에서 혹은 단체에서 어떠한 작업이 이루어질때 각 각의 시스템을 사용하게 된다.
하지만 여러 시스템을 사용하게 되면 각 각의 데이터형태가 다를 수 밖에 없다.
이를 통일하기 위해 JSON 포맷의 데이터 형식을 이용한다.
자바 측에서는 직렬화/역직렬화를 통해 자바시스템 외에서도 데이터를 사용할 수 있도록 바이트 형식의 데이터로 변환하는 기술이다.
여기서 말하는 바이트 형식의 데이터는 JSON 포맷처럼 문서가 된다고 보면 된다.
그리고 Spring 내의 내장되어 있는 Jackson을 이용하는 경우가 많다.
객체를 저장하거나 메모리, 데이터베이스 혹은 파일로 옮기때 필요한 것이 직렬화다.
다시말해 직렬화란? 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 객체를 바이트(byte) 형태로 바꾸는 것
객체에 저장된 데이터를 스트림에 쓰기(write) 위해 연속적인(serial) 데이터로 변환하는 것이다.
즉, 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것을 말한다.
직렬화의 주된 목적은 객체를 상태 그대로 저장하고 필요할 때 다시 생성하여 사용하는 것이다.
역직렬화는 직렬화의 반대말로, 네트워크나 영구저장소에서 바이트 스트림을 가져와서 객체가 저장되었던 바로 그 상태로 변환하는 것이다.
(convert it back to the Object with the same state).
직렬화하면서 생긴 바이트 스트림은 플랫폼에 독립적이다(platform independent).
직렬화된 객체는 다른 플랫폼에서 역직렬화가 가능하다는 뜻이다.
즉, 직렬화의 반대로 디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 다시 변환하는 것이다.
왜 필요한가?
주로 JVM의 메모리에만 상주되어 있는 객체 데이터를 그대로 영속화(persist)가 필요할 때 사용된다.
시스템이 종료되더라도 없어지지 않는 장점을 가지며 영속화된 데이터이기 때문에 네트워크로 전송도 가능하다.
그리고 필요할 때 직렬화 된 객체 데이터를 가져와서 역직렬화하여 객체를 바로 사용할 수 있게 된다.
또한 데이터 타입이 자동으로 맞춰지기 때문에 관련 부분을 큰 신경을 쓰지 않아도 되고, 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화, 역직렬화가 가능하다.
public static void main(String[] args){
Member member = new Memer("김철수", "deliverykim@baemin.com", 26);
byte[] serializeMember;
try(ByeArrayOutputStream baos= new ByteArrayOutputStream()){
try(ObjectOutputStream oos= new ObjectOutputStream(baos)){
oos.writeObject(member);
// serializedMember -> 직렬화된 member 객체
serializedMember = baos.toByteArray();
}
}
//바이트 배열로 생성된 직렬화 데이터를 base64로 변환
System.out.println(Base64.getEncoder().encodeToString(serializedMember));
}
public static void main(String[] args){
//직렬화 예제에서 생성된 base64 데이터
String base64Member="...생략";
byte[] serializedMember = Base64.getDecoder().decode(base64Member);
try(ByteArrayInputStream bais = new ByteArrayInputStream(serializedMember)){
try(ObjecInputStream ois = new ObjectInputStream(bais)){
//역직렬화된 member객체를 읽어온다.
Object objectMember = ois.readObject();
Member member = (Member)objectMember;
System.out.println(member);
}
}
}
Java 직렬화를 사용할 경우 역직렬화를 할 때 예외가 생길 수 있다는 사실을 인지하고 반드시 예외 처리를 해야한다.
또한 자주 변경되는 비즈니스적인 데이터를 Java 직렬화을 사용하지 않는다.
긴 만료시간을 가지는 데이터는 JSON 등 다른 포맷을 사용하여 저장해야 한다.
References (참고 자료)