IT/Java

Serialize란 무엇인가?

eternitys 2021. 4. 4. 23:56

코드를 쓰다 옆사람이 serialize가 뭔데 썼냐는 말에 저는 그냥 남들이 사용하길래 적었다.

 

라는 말도안되는 대답을 했습니다.

 

serialize가 무엇이고 왜 사용하는지 궁금하여 기록한 내용입니다.

 

Serialize(직렬화)가 무엇인가?

 

객체를 데이터스트림으로 만드는것이다. 

 

즉 객체에 저장된 데이터를 스트림에 쓰기위해 연속적인 데이터를 변환하는것.

 

반대로 스트림으로부터 데이터를 읽어 객체를 만드는것은 역직렬화(Deserialization)입니다.

 

직렬화 사용이유는 객체 자체를 영속적으로 보관할때 사용하는데 파일형태로 저장되어 네트워크를 통해 전송이 가능합니다.

 

장점으로는 자바와 자바시스템간 개발이 최적화가 되어있어 다른 라이브러리나 추가적인 환경구성이 필요없고

또한 역직렬화 할 경우 기존 객체처럼 사용이 가능합니다.

 

JVM(Java Virtual Machine)의 메모리에 상주(힙 or 스택)되어 있는 객체데이터를 바이트로 변환하는 기술입니다.

 

직렬화방법은 여러 Format이 존재합니다.

-표형태의 다량데이터를 직렬화 할때 CSV형태

-구조적인 데이터는 XML, JSON형태

 

자바에서 객체의 직렬화를 위해 ObjectOutputStream extends OutputStream을 사용합니다.

스트림에 객체를 출력하기위해 사용합니다 - writeObject()

 

 

출처 : https://www.c-sharpcorner.com/UploadFile/fd0172/introduction-to-serialization-in-java/

 

>정리하면서도 쉽게 이해가 되지않습니다.

 

객체나 데이터가 어느 특정 메모리상 사용되는데 이 상태그대로 저장하거나 네트워크 전송이 불가능하여

다른 환경에서 사용할수있게 바꾸는것이 serialize인것 같습니다.

쉽게 생각하면 직렬화는 바이트 형태로 바꾸는것이라 생각하면 될것같습니다.

 

 

--okky 댓글중 좋은댓글을 퍼왔습니다.

 

#지붕뚫고높이차님의 댓글

 

간단하게 이야기 드리면

서버가 다중화(여러개존재) 되어 있고
세션 클러스터링을 통해 세션관리를 하는 환경에서

도메인 객체가 세션에 저장이 될때

도메인 객체에
Serializable 인터페이스 클래스를 구현하기(implements) 해야지
정상적으로 세션에 저장하고 꺼내올수 있기 때문입니다.

도메인 객체가 세션에 저장하지 않는 단순한 데이터 집합이고
컨트롤러에서 생성되어서 뷰에서 소멸하는 데이터의 전달체라면
객체 직렬화는 고려하지 않아도 되는 부분입니다.

그리고 중간에 패턴 이야기가 나왔는데
메멘토 나 프록시 패턴에서 사용하는 객체는
도메인 객체의 성격보다는

메소드와 데이터를 포함하는 일반적인 객체 형태라서
질문하신 도메인 객체의 직렬화와 다른 내용인것 같아서
덧 붙입니다.


그런 점에서 보면

생각하지 않고
다른 코드에 적용되어 있으니 관습적으로
Serializable 를 구현한 도메인 객체를 많이 보시게 될거에요.



그런데

귀찮게 Serializable 인터페이스를 구현해야지만
객체 직렬화가 가능할까요?

모든
클래스와 그 클래스의 인스턴스, 데이터 집합은
컴퓨터 메모리에 잘 정렬되어
CPU 가 잘 사용하고 있고

메모리에 로드되어 있는 바이트 배열을
그대로 스토리지에 저장하거나
네트웍을 통해 다른 프로세스(JVM) 에 전달할 수 있는데

도대체 왜 Serializable 인터페이스가 필요한지 궁금해 하신분 계세요?




제 생각은 JVM 설계할때 인터페이스를 좋아하는 아키텍쳐가

객체 직렬화는
Serializable 인터페이스를 구현한 것 만
가능하게 설계한다!

라는 이유가 아닐까 추측합니다.
(추측입니다. 다른 이유를 아시는분은 알려주세요.)

jdk/jvm 설계자가 그렇게 인터페이스를 정의하니
자바 개발자는
그 규칙을 따라야 하는거라고 생각합니다.

 

-이 댓글의 질문

 

서버가 다중화되지 않고 단일화되어 있을때는
도메인 객체를 직렬화하지 않아도 도메인 객체를 세션에 저장할 수 있나요?

 

지붕뚫고높이차님의 답변

 

그건 서버설정에 따라 다릅니다.

세션관리를 스토리지나 네트웍자원을 사용한다고 하면 객체 직렬화를 해야 하고
메모리에서만 관리한다면 객체직렬화를 할 필요가 없습니다.

둘다 고려한다면 무조건 객체직렬화를 해야 겠죠.

 

-

 

#Jason Wang님의 댓글

 

오래된 글이지만 저도 추가 내용을 달아봅니다.

지붕뚫고높이차 님이 아주 자세하고 정확한 설명을 해 주셨습니다.

저는 좀더 언어 관점에서 설명드리겠습니다.

 

Java 든 C# 이든 C++ 이던 간에 데이터의 메모리 구조는 크게 다음 2가지로 나뉩니다.

- 값 형식 데이터: integer, float(single), charactor(또는 char 의 집합인 string) 등

- 오브젝트(레퍼런스) 형식 데이터: 메모리 번지(주소, Address)값 --> 주소값을 최종적으로 따라가면 값 형식 데이터를 참조 하게 됨. (C/C++) 또는 언어 차원에서 이 과정을 생략해줌 (C#, JAVA) --> 클래스의 인스턴스는 해당 프로세스의 메모리 상에서만 유효한 번지 주소를 갖는 오브젝트(레퍼런스) 데이터.


이 중에 '저장/전송 가능한 데이터' 는 당연하게도 값 형식 데이터만 전송 가능합니다.


오브젝트(레퍼런스) 형태의 참조 데이터(메모리 번지 주소 데이터)는 상식적으로도 파일 저장이나 네트워크 전송이 불가능합니다.

 

일례로 32비트 시스템에서 Class A 의 인스턴스를 만들었고, 그 참조/주소값이 0x00121212 이었습니다.

그리고 이 참조/주소값 자체도 강제로 파일에 포함 시켜 저장하였습니다.

하지만 다음에 프로그램(서비스)를 다시 Start 시키고 이전에 저장했던 파일에서 0x00121212 참조/주소를 다시 읽어와도 클래스 A 의 인스턴스는 부활 할 수 없으며 이해할 수 도 없는 쓰레기 값일 뿐입니다.

네트워크 전송도 마찬가지로 받는 상대방 입장에서는 전달자가 사용한 참조/주소값 자체는 무의미 합니다. 서로 물리적으로 사용중인 메모리 공간(OS의 가상메모리 포함)은 일치하지 않기 때문입니다.

 

비트와 바이트와 메모리, 언어 등의 관점에서 이야기를 해보니 이렇습니다.

조금 더 이해를 돕고자 JAVA 언어의 관점에서 설명해 보겠습니다.

 

자바는 내부적으로 오브젝트(또는 Reference) 형식의 데이터를 많이 사용합니다.

그리고 오브젝트의 주소 메모리 번지 값 접근/편집을 일반적인 JAVA 코딩에 쓰지 않습니다.
(언어 차원에서 내부적으로 해결 해 줌)

 

JAVA 의 클래스 설계에는 오브젝트 안에 오브젝트가 또 들어있을 수 있습니다. (인스턴스 포함 관계)

그것은 오브젝트 안에 내부적으로 다른 오브젝트를 참조할 수 있는 주소값이 담긴 것을 의미합니다.

 

이 주소값의 실체를 다 끌어와서 Primitive 한 값 형식 데이터로 전부 변조하는 작업을 바로 직렬화(Serialization)라 합니다.

--> XML, JSON 등의 데이터 구조를 떠올리면 이해가 빠를것입니다.
--> C/C++ 을 해보셨다면 좀 더 이해가 빠를 것입니다. (포인터 데이터를 모두 실제 값의 묶음 형식으로 전달, NPOD 데이터를 POD 데이터로 전달, 그리고 한방에 memcpy!)

 

그리고 직렬화 된 데이터 형식은 언어에 따라 텍스트로 된 데이터 또는 바이너리 등의 모양을 띄게 됩니다. (어차피 텍스트든 바이너리든 결국 둘 다 Primitive 한 값들의 집합임)


결국 직렬화가 된 데이터는 최종적으로 오브젝트 타입이 없습니다. 모든것이 Primitive 한 값 형식의 데이터 묶음이며, 이것은 파일 저장이나 네트워크 전송시 파싱 할 수 있는 유의미한 데이터가 되는 것입니다. (데이터 중복을 줄이기 위한 테이블화가 일어나는지는 확인 필요. 어차피 이 부분은 언어마다, 규약마다 다를 것)

 

그리고 또하나 특징은 현존하는 컴퓨터 머신들의 메모리 설계상 큰 데이터 덩어리를 순차적으로 읽어 오는 것이 가장 빠르기 때문에 직렬화 된 데이터는 RDBMS 구조랑은 완전 다르게, 일직선의 연속적인 값들의 집합인 형태를 띄게 됩니다. (대게 그렇습니다. 이것도 언어/규약 마다 다를 수 있습니다)

그래서 이렇게 전송/저장 가능한 데이터를 만드는 행위에 '직렬화(Serialization)' 라는 이름이 붙게 되었습니다.

 


정리하면 직렬화는 보통 파일 저장이나, 패킷 전송시에 '파싱할 수 있는 데이터를 만들기 위해' 사용됩니다.


+@ 로 프로세스 간에 데이터 전송에도 직렬화된 데이터가 사용 되는 이유는
대부분의 OS 가 현재 가상메모리를 운영 중이며 대부분의 OS 의 프로세스 구현은 서로 다른 가상메모리주소공간(Virtual Address Space, VAS) 를 갖기 때문에 역시 마찬가지로 오브젝트 타입의 참조값(결국 주소값)데이터 인스턴스를 직접 줄 수 없어서 직렬화된 데이터로의 교환을 주로 사용합니다.

 

 

참조

okky.kr/article/224715

 

atoz-develop.tistory.com/entry/JAVA%EC%9D%98-%EA%B0%9D%EC%B2%B4-%EC%A7%81%EB%A0%AC%ED%99%94Serialization%EC%99%80-JSON-%EC%A7%81%EB%A0%AC%ED%99%94

nesoy.github.io/articles/2018-04/Java-Serialize

 

medium.com/@hhs1253/%EC%A7%81%EB%A0%AC%ED%99%94-serialization-861ccaa2ca4f

 

직렬화(Serialization)

직렬화란 객체를 데이터 스트림으로 만드는 것을 말한다. -> 객체에 저장된 데이터를 스트림에 쓰기위해 연속적인 데이터로 변환하는 것이다. 반대로 스트림으로부터 데이터를 읽어서 객체를

medium.com

 

m.blog.naver.com/PostView.nhn?blogId=magnking&logNo=221156324082&proxyReferer=https:%2F%2Fwww.google.com%2F

 

직렬화(serialization)란?

직렬화라는 단어가 저에게는 참 어려웠습니다. 그래서 직렬화에 대해서 약간 알게 된 부분을 공유하려고 합...

blog.naver.com