(안드로이드) 객체직렬화

*컴포넌트와 컴포넌트간에 데이터 전달을 위해서는 객체직렬화가 필요하다.
객체 직렬화는 Serializable객체를 통해 구현가능하고
추가적으로 Bundle,Parcel, Parcelable객체도 직렬화를 지원한다.


1. Serializable객체

직렬화의 기본 개념은 간단하다.
객체는 메모리에 존재하는 것이다.(new를 통해 객체 생성된 것)
이렇게 메모리에 존재하는 것을 파일 혹은 네트워크를 통해 저장 및 전송할 수 있을까?
객체 자체는 함수와 변수들이 존재한다.
함수와 변수는 메모리의 다른영역에 저장된다.(함수=code영역, 변수=heap영역)
이것을 그대로 파일/네트워크 등으로 전송/저장한다는 것은 쉽지않다.
직렬화는 함수는 신경쓰지 않고 단지 변수를 직렬화시킨다.(byte코드로 순차적으로 나열시킨다.)

왜 그럴까?
함수를 포함한 Class는 데이터가 아니다.
단지 코드일 뿐이다.
그러므로 Class파일만 있으면 참조가 가능하다.
(송신측에 xxx.java, 수신측에 xxx.java 코드만 동일하게 존재하면 해결된다.)
그러나 변수는 다르다. 변수는 데이터이므로 코드로 가질 수 없다.
그러므로 직렬화는 이 변수 데이터들을 어떻게 전달하느냐에 관점을 둔다.
아래를 보자.


Class 내 함수는 신경쓰지 않고 단지 변수만 직렬화 시킨다.
직렬화 개념은 변수 데이터를 순차적으로 byte코드로 나열하는 것이다.
이렇게 byte코드로 나열되면 이 데이터는 무엇이든 전송이 가능한 것이다.
아래 1번과 같이 객체를 직렬화 하고
2번과 같이 byte코드를 File이든 네트워크든 메모리든 쓸 수 있다.
만일 다시 객체화 시킬때는 4번과 같이 byte코드를 읽고 역직렬화 과정을 거치면
원래 객체를 복원할 수 있는 것이다.
역직렬화 과정에서는 Class코드를 참조하게 된다.


직렬화 방법은 "Serializable"을 상속받으면 자동으로 직렬화 처리되어 객체가 생성된다.
하지만 주의할 점이있다.
위처럼 직렬화 객체내에 또 다른 객체를 포함하는 경우
포함되는 객체 또한 "Serializable"을 상속 받아야만 한다.
그럼 "Serializable"객체가 무엇인데 자동으로 직렬화 처리를 해줄까?


위 처럼 "Serializable"이라고 마킹해 두면 시스템 내부적으로 객체를 직렬화 시켜 저장하느 것이다.
직렬화 Class를 생성할 때 꼭 지켜야할 조건이 있다.
아래를 보자.


1번과 같이 송신측과 수신측에 동일한 Class가 존재해야 한다.
2번과 같이 패키지명이 같아야 한다.
패키지 명이 다르면 송신측에서 보낸 객체가 수신측에서 받을 때, 다른 객체라고 보고 역 직렬화를 할 수 없다.

3번과 같이 꼭 Serializable을 상속받아야 한다.
4번과 같이 꼭 serialVersionUID를 선언하고 같은 값을 가져야 한다.

serialVersionUID은 객체에 대한 버전과 같다.
이 버전이 수신측과 송신츠이 다르면 송신측에 보낸 객체를 수신측에서 받을 때 객체는 동일한 객체로 보나, 객체 자체의 내용이 달라졌다고 보고 역직렬화를 하지 못한다.

그렇다면 아래과 같이 Sample코드를 보자.
아래와 같이 메모리를 통해 객체를 전달할 것이다.


그런데 왜 Local 단말에서 객체 직렬화가 필요할까?
아래를 보자




각기 다른 Process들은 그 Process내 메모리를 공유할 수 없다.
그러므로 다른 Process에 어떤 데이터를 전달하기 위해서는 IPC란 기법을 사용해야 한다.
Android에서는 Open Binder라는 드라이버를 통해 적용된다.
IPC는 byte stream 전송이 가능하므로 직렬화가 필요한 것이다.



참고 사이트: http://rockdrumy.tistory.com/1044

댓글

이 블로그의 인기 게시물

(18장) WebSocekt과 STOMP를 사용하여 메시징하기

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬