직렬화(Serialization)란? (feat. Java)

문지원(JiwonMoon)·2022년 11월 14일
0

목적

가장 먼저 직렬화/역직렬화를 개념의 이해전에 왜 사용하는지를 알아야 한다.
기업에서 혹은 단체에서 어떠한 작업이 이루어질때 각 각의 시스템을 사용하게 된다.
하지만 여러 시스템을 사용하게 되면 각 각의 데이터형태가 다를 수 밖에 없다.
이를 통일하기 위해 JSON 포맷의 데이터 형식을 이용한다.

자바 측에서는 직렬화/역직렬화를 통해 자바시스템 외에서도 데이터를 사용할 수 있도록 바이트 형식의 데이터로 변환하는 기술이다.

여기서 말하는 바이트 형식의 데이터는 JSON 포맷처럼 문서가 된다고 보면 된다.
그리고 Spring 내의 내장되어 있는 Jackson을 이용하는 경우가 많다.

직렬화(Serialization)란?

객체를 저장하거나 메모리, 데이터베이스 혹은 파일로 옮기때 필요한 것이 직렬화다.

다시말해 직렬화란? 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 객체를 바이트(byte) 형태로 바꾸는 것
객체에 저장된 데이터를 스트림에 쓰기(write) 위해 연속적인(serial) 데이터로 변환하는 것이다.

즉, 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것을 말한다.

직렬화의 주된 목적은 객체를 상태 그대로 저장하고 필요할 때 다시 생성하여 사용하는 것이다.

역직렬화(Deserialization)란?

역직렬화는 직렬화의 반대말로, 네트워크나 영구저장소에서 바이트 스트림을 가져와서 객체가 저장되었던 바로 그 상태로 변환하는 것이다.
(convert it back to the Object with the same state).

직렬화하면서 생긴 바이트 스트림은 플랫폼에 독립적이다(platform independent).
직렬화된 객체는 다른 플랫폼에서 역직렬화가 가능하다는 뜻이다.

즉, 직렬화의 반대로 디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 다시 변환하는 것이다.

사용이유

왜 필요한가?

  1. 자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 역직렬화를 포함한다.
  1. 시스템적으로 JVM의 런타임 데이터 지역에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말하기도 한다.

주로 JVM의 메모리에만 상주되어 있는 객체 데이터를 그대로 영속화(persist)가 필요할 때 사용된다.

시스템이 종료되더라도 없어지지 않는 장점을 가지며 영속화된 데이터이기 때문에 네트워크로 전송도 가능하다.

그리고 필요할 때 직렬화 된 객체 데이터를 가져와서 역직렬화하여 객체를 바로 사용할 수 있게 된다.

또한 데이터 타입이 자동으로 맞춰지기 때문에 관련 부분을 큰 신경을 쓰지 않아도 되고, 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화, 역직렬화가 가능하다.

조건 및 방법

  • 직렬화 조건
    • ava.io.Serializable 인터페이스를 상속받은 객체는 직렬화할 수 있는 기본조건이다.

직렬화 방법

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));
}
  • 역직렬화 조건
    • 직렬화 대상이 된 객체의 클래스가 클래스 패스에 존재해야하며, import 되어 있어야 한다.
    • 중요한 점은 직렬화와 역직렬화를 진행하는 시스템이 서로 다를 수 있다는 것을 반드시 고려한다.
    • 자바 직렬화 대상 객체는 동일한 serialVersionUID 를 가지고 있어야 한다.
      (private static final long serialVersionUID= 1L;)

역직렬화 방법

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 (참고 자료)

0개의 댓글