관리 메뉴

드럼치는 프로그래머

[안드로이드] Activity에 대해서 - 객체 직렬화편(Serializable) 본문

★─Programing/☆─Android

[안드로이드] Activity에 대해서 - 객체 직렬화편(Serializable)

드럼치는한동이 2013. 5. 31. 11:38

4. 객체 직렬화에 대해서

 

사실 순수하게는 Activity와 객체 직렬화는 다른 얘기이다.

그런데 왜 꼭 이 장에서 객체 직렬화에 대해서 다루고 있는 것일까?

앞으로 배우게 될 각 components 와 components 간에

데이터 전달에 관련한 Intent에서 객체 직렬화가 많이 이용된다.

물론 Activity component에서도 intent라는 녀석을 사용하므로

객체 직렬화에 대한 이해는 꼭 필요하다.

객체 직렬화는 Serializable 객체를 통해 구현 가능하고

추가적으로 Bundle, Parcel, Parcelable 객체도 직렬화를 지원한다.

특히 Bundle, Parcel, Parcelable 객체는 안드로이드 전역에 걸쳐

사용된다.

 

4.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(Inter Process Communication)란 기법을 사용하여야 한다.

Android 에서는 Open Binder라는 드라이버를 통해 적용된다. (Service에서 다시 언급하겠다.)

IPC는 byte stream 전송이 가능하므로 직렬화가 필요한 것이다.

아래와 같이 두 가지 apk를 구현하고

송신측 Process에서 보낸 객체를 수신측에서 복구할 것이다.

 

 

 

[송신측 패키지 구현]

코드 구성은 아래와 같다.

 

 

우선 직렬화할 객체를 구현하자.

 

 

1 번과 같이 패키지 명을 잘 정하자. (수신측에도 같은 패키지 명으로 해야 한다.)

2 번과 같이 Serializable을 상속 받자.

3 번과 같이 serialVersionUID를 정의 하자.

4 번과 같이 전달한 변수를 추가한다.

아래와 같이 Layout파일을 작성하자.

객체 전달 지시를 위해 버튼을 추가한 것이다.

 

 

자 마지막으로 아래와 같이 객체 전달할 코드를 Activity 코드에 추가한다.

 

 

아직 Intent에 대해서 배우지 않았으므로

그냥 빨강색 부분만 살펴보자.

직렬화 객체를 생성하여 intent에 담았다고만 생각하면 된다.

intent에 담기 데이터는 다른 Process로 전달이 가능하다.

직렬화 객체의 변수에 값을 저장했다.

차후 이 객체가 수신측에 전달될때,

그 값이 정상적으로 전달되었는지 확인해 보면 된다.

실행해 보면 아래와 같은 화면이 나타난다.

 

 

수신측 패키지를 만들지 않았으므로 객체를 전송하는 버튼을 누르면 안된다.

 

[수신측 패키지 구현]

코드 구성은 아래와 같다.

 

 

우선 직렬화할 객체를 구현하자.

그냥 송신측 패키지 코드를 복사하면 된다.

패키지 명을 같게 하는 것을 주의하자.

 

 

송신측과 완전히 같게 해 주면 된다.

송신측에서 보낸 객체의 내용을 출력하기 위해

Layout에 TextView를 추가하였다.

 

 

자 송신측에서 보낸 데이터를 출력하는 코드를 작성하자.

 

 

아직 Intent에 대해 배우지 않았으므로

빨강생 코드만 이해하자.

이제 수신측 패키지를 설치하자.

잠시 본 과정을 설명하자면,

송신측 Activity에서 지금 작성한 수신측 Activity를 호출할 것이다.

송신측에서 수신측 Activity를 호출할 때 intent 객체를 넘겨 준다.

intent 객체내에는 직렬화 객체가 들어가 있다.

수신측에서는 이 객체를 읽어들어 객체의 내용을 출력한 과정이다.

아래는 송신측 Activity를 실행한 화면이다.

버튼을 눌러보자.

 

 

수신측 Activity가 호출되고

송신측에서 보낸 객체의 내용이

정상적으로 출력되었음을 알 수 있다.

 

 

[출처] http://cafe369.daum.net/_c21_/bbs_search_read?grpid=1MWA2&fldid=aAfL&datanum=73&contentval=&docid=1MWA2aAfL7320110321094557

Comments