관리 메뉴

Rootable의 개발일기

직렬화와 역직렬화 본문

Java

직렬화와 역직렬화

dev-rootable 2024. 5. 3. 17:43

출처: https://www.pexels.com/ko-kr/photo/17485657/

 

📌 정의

 

✅ 직렬화(Serialization)

 

데이터를 디스크에 저장하거나, 네트워크 통신에 사용하기 위한 형식으로 변환하는 것

 

✅ 역직렬화(Deserialization)

 

디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 변환하는 것

 

❓ 직렬화가 필요한 이유

 

자바에는 원시타입(Primitive Type)과 주소값을 갖는 참조형 타입이 있다.

 

원시 타입은 스택에 저장되며, 값 자체가 그대로 저장되기 때문에 값을 일정한 형식의 raw byte 형태로 변경하여 외부로 전달할 수 있다.

 

반면, 객체 데이터는 Heap 영역에 존재하고 스택에는 Heap 영역에 존재하는 객체의 주소(메모리 주소)를 갖는 식으로 저장된다. 그렇다면 외부로 전달하는 데이터는 객체의 주소가 된다. 각 PC마다 사용하는 메모리 공간 주소가 다르고, 프로그램이 종료되면 Heap 데이터는 소멸하기 때문에 주소를 전달하는 것은 무의미하다.

 

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

 

🔍 자바 직렬화 사용처

 

✅ 서블릿 세션

 

세션을 서블릿 메모리 위에서 운용한다면 직렬화가 필요 없지만, 파일로 저장하거나 세션 클러스터링, DB를 저장하는 옵션 등을 선택하게 되면 세션 자체가 직렬화가 되어 전달된다. 그래서 세션에 필요한 객체는 java.io.Serializable 인터페이스를 구현하는 것이 좋다.

 

✅ 캐시

Encache, Redis, memcached 등의 라이브러리 시스템에서 캐시 할 부분을 자바 직렬화된 데이터를 저장해서 사용한다. 다른 직렬화 방식도 사용되지만, 자바 직렬화가 가장 간편해서 많이 사용된다.

 

✅ 자바 RMI

 

원격 시스템 간의 메시지 교환을 위해서 사용하는 자바에서 지원하는 기술이다. 원격 시스템의 메서드를 호출 시에 전달하는 메시지를 자동으로 직렬화하고, 전달받는 원격 시스템에서는 메시지를 역직렬화하여 사용한다.

 

💡 직렬화에 적합한 객체

- 짧은 만료 시간을 지니는 데이터를 가지고 있는 객체
- 거의 변경되지 않는 데이터를 지닌 객체

 

🔨 직렬화 구현

 

📢 Serializable 인터페이스 구현

 

class ClassA implements Serializable {
}

 

📢 Serializable 인터페이스를 구현한 클래스 상속

 

class ClassB extends ClassA {
}

 

💡 transient

 

특정 필드를 직렬화하고 싶지 않은 경우 transient 키워드를 붙이면, 그 타입의 기본값으로 직렬화된다.

 

만약, 직렬화할 수 없는(Serializable을 구현하지 않는) 객체를 필드 멤버로서 갖고 있다면, InvalidClassException 예외가 발생하여 직렬화할 수 없다.

 

💥 Case. 객체 멤버가 추가되거나 타입이 변경되는 경우

 

local class incompatible: stream classdesc serialVersionUID = 111, local class serialVersionUID = 222

 

클래스 멤버 변수의 타입 또는 이름이 변경되거나 새로운 멤버 변수가 추가되는 경우, 역직렬화 과정에서 위와 같은 에러가 발생한다.

 

위 에러는 serialVersionUID가 일치하지 않는다는 메시지로, 클래스의 변화로 serialVersionUID도 새로운 값으로 변경되어 기존에 알고 있던 값과 일치하지 않아 발생한 에러다.

 

class ClassA implements Serializable {
    private static final long serialVersionUID = 1L;
    ...
}

 

위와 같이 serialVersionUID를 명시해 준 뒤, 다시 직렬화를 하면 클래스에 변화가 생겨도 역직렬화 과정에서 에러가 발생하지 않는다. 기존 멤버 변수의 삭제도 영향을 주지 않는다.

 

단, 기존 멤버 변수의 타입이 변경되는 경우에는 다시 에러를 일으킨다.

 

Exception in thread "main" java.io.InvalidClassException: test.ClassA; incompatible types for field ...

 

📝 결론

자바에서 제공하는 직렬화 기능은 추가적인 라이브러리 없이 객체 데이터를 네트워크에 태울 수 있지만, 직렬화 결과물 용량이 상대적으로 커서 비효율적인 문제를 갖고 있다. 또한, 자주 변경될 수 있는 데이터는 역직렬화 과정에서 에러가 발생할 가능성이 있다.

 

References:

 

https://inkyu-yoon.github.io/docs/Language/Java/Serialization

 

· JAVA 직렬화(Serialization)과 역직렬화(Deserialization)

👩🏻‍💻 지식 창고 📚

inkyu-yoon.github.io

 

https://steady-coding.tistory.com/576

 

[Java] 직렬화와 역직렬화

java-study에서 스터디를 진행하고 있습니다. 데이터 직렬화와 역직렬화 데이터 직렬화 메모리를 디스크에 저장하거나, 네트워크 통신에 사용하기 위한 형식으로 변환하는 것이다. 데이터 역직렬

steady-coding.tistory.com

 

'Java' 카테고리의 다른 글

List  (0) 2024.05.08
Java Collection Framework  (0) 2024.05.08
Thread  (0) 2024.05.03
Java의 I/O  (0) 2023.09.15
래퍼 클래스(Wrapper Class)  (0) 2023.09.13