본문 바로가기

JAVA

클래스에 Serializable을 구현하는 이유(class implements Serializable)

질문:

 

자바책에는 객체를 파일에 저장하거나 파일에서 꺼내오기 위해서 또는 객체를 네트워크를 통해 전송하기 위해서는 미리 객체를 직렬화해야한다고 되어 있네요.

웹 어플 소스 분석하다보면
서비스 객체나 컨트롤러 객체는 직렬화하지 않는데
도메인 객체(DB에서 읽어온 내용을 담는 객체)는
꼭 implement serializable로 직렬화 하는데
이유가 궁긍합니다.

 

답변1:

 

간단하게 이야기 드리면

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

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

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

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

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

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


그런 점에서 보면

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



그런데

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

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

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

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




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

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

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

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

 

답변2:

 

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) 를 갖기 때문에 역시 마찬가지로 오브젝트 타입의 참조값(결국 주소값)데이터 인스턴스를 직접 줄 수 없어서 직렬화된 데이터로의 교환을 주로 사용합니다

 

스크랩:https://okky.kr/article/224715

'JAVA' 카테고리의 다른 글

[Java] Collections의 차이(List, Set, Map)  (0) 2018.06.15
HTML 특수문자 변환  (0) 2018.02.02
String==null 과 String.isEmpty() 의 차이  (0) 2017.12.06
lombok의 개념 및 활용  (0) 2017.11.30
Vector,ArrayList, LinkedList의 차이  (0) 2017.11.29