Skip to content

Latest commit

 

History

History
139 lines (99 loc) · 6.6 KB

01.md

File metadata and controls

139 lines (99 loc) · 6.6 KB

직렬화(Serialization) 란?

직렬화는 사실 자바에만 있는 개념은 아니고, Computer Science에서 정의되어 널리 사용되는 개념이다.

Computer Science에서 직렬화(serialization)은 다음과 같이 정의하고 있다.

"데이터 구조나 오브젝트 상태를 동일하거나 다른 컴퓨터 환경에 저장(파일이나 메모리 버퍼에서, 또는 네트워크 견경 링크 간 전송 등)하고, 나중에 재구성할 수 있는 포맷으로 변환하는 과정이다."

변환된 데이터는 다시 원래 데이터로 변환이 가능하며, 이러한 과정을 역직렬화(deserialization)이라고 한다.

그렇다면, 자바에서는 직렬화를 어떻게 정의하고 있을까?

  • 자바 직렬화자바 시스템 내부에서 사용되는 객체 또는 데이터외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 말한다.
  • 시스템적으로는 JVM(Java Virtual Machine)의 메모리에 상주(heap 또는 stack)으로 되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말한다.

Computer Science에서 말하는 직렬화(Serialization)과 같은 개념임을 알 수 있으며, 자바에서는 직렬화 시 데이터(object)를 바이트(byte) 스트림 형태로 변환한다는 것을 알 수 있다.

직렬화 방법

자바 직렬화를 하기 위해서 type이 primitive type(기본형 타입)이거나 java.io.Serializable 인터페이스를 상속 받아야 한다.

Serializable 인터페이스의 선언부를 보면 다음과 같이 비어있는 것을 볼 수 있는데,

다른 특별한 기능 없이 Serializable 인터페이스를 구현한 객체는 직렬화가 가능하다는 걸 알 수 있는 용도로만 사용된다.

package java.io;
public interface Serializable {}

직렬화 테스트를 위해서 Serializable 인터페이스를 구현한 User 클래스를 선언해보자.

static class User implements Serializable {
  private String name;
  private int age;
  private String email;

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

  @Override
  public String toString() {
      return "User{" +
              "name='" + name + '\'' +
              ", age=" + age +
              ", email='" + email + '\'' +
              '}';
  }
}

직렬화를 하기 위해서는 java.io.ByteArrayOutputStream, java.io.ObjectOutputStream을 이용하면 된다.

public static String serialize(User user){
  String serializedUserBase64;

  try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){
      try(ObjectOutputStream oos = new ObjectOutputStream(baos)){
          oos.writeObject(user);
          //직렬화(byte array)
          byte[] serializedUser = baos.toByteArray();
          //byte array를 base64로 변환
          serializedUserBase64 = Base64.getEncoder().encodeToString(serializedUser);
          return serializedUserBase64;
      }
  } catch(IOException e){
      e.printStackTrace();
  }
  return null;
}
serializedUserBase64 = rO0ABXNyAAlNYWluJFVzZXIPO9q2u0FthwIAA0kAA2FnZUwABWVtYWlsdAASTGphdmEvbGFuZy9TdHJpbmc7TAAEbmFtZXEAfgABeHAAAAAUdAAPaGVsbG9AZ21haWwuY29tdAAFaGVsbG8=

이번에는 위에서 직렬화하여 Base64 값으로 변환한 값을 다시 원래 객체로 역직렬화 해보겠다.

역직렬화시에는 java.io.ByteArrayInputStream, java.io.ObjectInputStream 을 이용하면 된다.

단, 역직렬화를 하기 위해서는 직렬화 대상이 된 객체의 클래스가 클래스 패스에 존재해야 하며, import 되어 있어야 한다.

public static User deserialize(String serializedBase64){
  byte[] serializedUser = Base64.getDecoder().decode(serializedBase64);
  try(ByteArrayInputStream bais = new ByteArrayInputStream(serializedUser)){
      try(ObjectInputStream ois = new ObjectInputStream(bais)){
          Object objectUser = ois.readObject();
          return (User) objectUser;
      } catch (ClassNotFoundException e) {
          throw new RuntimeException(e);
      }
  } catch(IOException e){
      e.printStackTrace();
  }

  return null;
}
deserializedUser = User{name='hello', age=20, email='hello@gmail.com'}

제대로 역직렬화 되었음을 확인할 수 있다.

언제, 왜 사용하는가?

데이터를 직렬화하는 자바 직렬화뿐만 아니라 CSV, XML, JSON 으로의 직렬화도 존재한다.

실제로 표 형태의 다량의 데이터를 저장하거나 전송할 때 CSV를 많이 사용하고, 네트워크에서 구조적인 데이터를 송수신 할 때(API 시스템) 대부분 JSON을 많이 사용한다.

CSV로 직렬화 시엔 Apache Commons CSV, opencsv 등의 라이브러리를 많이 사용하고, JSON으로 직렬화시엔 Jackson, GSON 등의 라이브러리를 많이 이용한다.

그렇다면 위의 CSV, JSON으로의 직렬화를 이용하면 되는데, 굳이 자바 직렬화를 왜 사용할까?

자바 직렬화 같은 자바 시스템에서의 데이터 전송(다른 JVM 환경의 시스템으로의 전송), 저장에 최적화 되어있다.

데이터 구조가 복잡하더라도 직렬화의 기본 조건만 잘 지키면 바로 직렬화와 역직렬화가 가능하다.

무엇보다 데이터 타입이 자동으로 맞춰지기 때문에 역직렬화시 바로 기존 객체처럼 사용이 가능하다.

개발자가 일일이 타입을 맞춰 줄(형변환) 필요가 없기 때문에 상당히 편리하다.

물론 개발할 때는 Jackson 등의 라이브러리를 사용하면 된다.

이러한 특성 때문에 자바 직렬화는 다음과 같은 경우에 사용된다.

서블릿 세션(Servlet Session)

서블릿 기반의 WAS(톰캣, 웹 로직)들은 대부분 세션의 자바 직렬화를 지원하고 있다. 단순히 메모리 위에서 운용하는 세션이 아닌(서버 재시작시 초기화) 클러스터링 환경에서 세션 공유를 위해 파일로 저장하거나 DB에 저장할 때 세션 객체를 자바 직렬화를 사용하여 저장할 수 있다.

캐시(Cache)

실시간으로 반복적으로 DB에서 조회하는 데이터가 아니라면, 리소스 절약을 위해 주로 캐시(메모리 DB) 라이브러리 시스템에 데이터를 저장해 놓고 사용하게 되는데, 이 때 데이터를 자바 직렬화하여 저장할 수 있다.

등등...