[Java] - 직렬화,역직렬화

링딩·2023년 4월 15일
0

Computer Science

목록 보기
33/49




들어가기 앞서 ​Java에서 말하는 객체 직렬화는 이처럼 Java의 객체를 외부로 저장/복원하거나 네트워크 상으로 전송할 수 있도록 바이트 형태로 변환하는 기술을 의미한다.

반대로 '역직렬화'는 직렬화를 통해 변환된 바이트 형태를 다시 원상태인 객체로 변환 시키는 기술을 의미한다.


들어가기 전... 왜 직렬화가 필요한데요?

직렬화를 하게 되면 각 주소 값이 가지는 데이터를 전부 끌어 모아서 값 형식 데이터로 변환해 준다. 직렬화가 된 데이터는 언어에 따라서 텍스트 또는 바이너리 등의 형태가 되는데, 이러한 형태가 되었을 때 저장하거나 통신할 때 파싱이 가능한 유의미한 데이터가 되기 때문이다.


직렬화와 역직렬화


public class Member implements Serializable {
    private String name;
    private String email;
    private int age;

    public Member(String name, String email, int age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }
    @Override
    public String toString() {
        return String.format("Member{name='%s', email='%s', age='%s'}", name, email, age);
    }
}

🔎 직렬화 란?

◽ 조건

  1. java.io.Serializable 인터페이스를 구현해야 한다
    -> Serializable 인터페이스를 구현하는 클래스로 만든다.

여기서 Serializable은 현재 클래스의 객체가 직렬화가 제공되어야 함을 JVM에게 알려주는 역할만 수행한다.

◽ 직렬화 하는 방법

java.io.ObjectOutputStream 를 사용

public static void main(String[] args){
    Member member = new Member("김배민", "deliverykim@baemin.com", 25);
    byte[] serializedMember;
    try (ByteArrayOutputStream 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));
}



🔎 역직렬화 란?

◽ 조건

  • 직렬화 대상이 된 객체의 클래스가 class path에 존재해야 하며 import 되어 있어야 한다.
  • 자바 직렬화 대상 객체는 동일한 serialVersionID를 가지고 있어야 한다.

+) class path는?
JVM이 프로그램을 실행할 때, class 파일을 찾는 데 기준이 되는 파일 경로


◽ 역직렬화 하는 방법

java.io.ObjectInputStream 를 사용

public static void main(String[] args){
    // 직렬화 예제에서 생성된 base64 데이터
    String base64Member = "...생략";
    byte[] serializedMember = Base64.getDecoder().decode(base64Member);
    try (ByteArrayInputStream bais = new ByteArrayInputStream(serializedMember)) {
        try (ObjectInputStream ois = new ObjectInputStream(bais)) {
            // 역직렬화된 Member 객체를 읽어온다.
            Object objectMember = ois.readObject();
            Member member = (Member) objectMember;
            System.out.println(member);
        }
    }
}



직렬화의 장점

  1. 자바 시스템 개발에 최적화 되어 있다.
  2. 복잡한 데이터 구조를 가진 객체일지라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화, 역직렬화가 가능
  3. 데이터 타입이 자동으로 맞춰진다.
    -> 이 덕에 역직렬화가 되면 기존 객체처럼 바로 사용이 가능하다.



역직렬화의 단점

앞서 말한 것처럼 역직렬화를 하게 되면 클래스의 구조가 변경된다는 문제가 발생한다.

1. 너무 엄격한 타입 체크

변수 타입이 달라지면 타입 예외가 발생한다. 직렬화한 데이터의 객체의 변수 타입이 String인데, 추후 개발하면서 StringBuilder로 바꿨다면 역직렬화가 불가능하다. int를 long으로 바꾸는 것이다.

2. 용량 문제

일반적인 메모리 기반의 Cache에서는 Data를 저장할 수 있는 용량의 한계가 있으므로 json 형태와 같은 경량화된 형태로 직렬화하는 것이 좋다.


자바 직렬화는 언제 쓰는가?

  • 짧은 만료 시간을 지니는 데이터를 가지고 있는 객체를 직렬화 할 때
  • 거의 변경되지 않는 데이터를 지닌 객체를 직렬화 할 때

참조 변수는 주소값을 쓰다 보니 직렬화에서 쓰지 않는다!!!

역직렬화는 생성자 없이 하다 보니 보안성으론 좋지 않다



출처

steady-coding님의 글을 참조하여 작성하였습니다.



profile
초짜 백엔드 개린이

0개의 댓글