안드로이드는 잘 알다시피
액티비티, 서비스, 브로드캐스트리시버, 컨텐츠제공자 가 있다.
어플을 개발하면서 액티비티나 프래그먼트를 주로 다뤄와서 다른 기능들에 대해서는 좀 생소하게 느껴졌다.
그중에 이용해 본 것이 서비스를 통해서 데이터를 받고 이를 통해 작업표시줄에 올려주는 fcm서비스 정도랄까....
간단하게 정리를 해보자면
서비스는 백그라운드나 포그라운드 상에서 어플의 진입점이 될 수 있는 중요한 요소이고,
브로드캐스트 리시버는 시스템의 환경이나 다른 변화에 의해서 생기는 반응을 앱에서 알 수 있도록 해 주고,
(충전중, 비행기모드로 변함 등..)
콘텐츠 제공자는 앱 외부와의 데이터 공유를 관리한다고 보면 되겠다.
위와 같이 다양한 앱 진입점이 있는 것이 안드로이드 앱의 구조를 복잡하게 만든다. 데스크탑의 앱은 명확한 진입점이 하나만 있기 때문이다. 그리고 우리는 짧은 시간에 이 어플 저 어플을 드나들기 때문에 사용자의 동작에 따라 자연스러운 사용감을 주기 위해서는 각각의 구성요소는 독립적이어야 하고, 앱 데이터를 구성요소가 가져서는 안 된다. 그러므로 우리는 안드로이드 아키텍쳐에 대해서 잘 알아야 한다.
안드로이드 어플리케이션의 경우 다른 어플리케이션을 킨다는 말은 다른 어플리케이션의 컴포넌트를 킨다는 말이지 그 어플리케이션 전체를 실행한다는 것과는 다르다.
안드로이드 아키텍쳐의 경우는 많이 언급되지만 어느정도 공부를 하고 다시 읽어보고 이 과정을 반복하는게 좋다.
안드로이드 아키텍쳐 원칙
1. 관심사 분리
모바일 특성상 리소스 제한에 의해 언제든 os가 구성요소를 프로세스에서 제거할 수도 있고, 사용자가 임의로 제거 할 수도 있는데, 이것을 우리 개발자는 막을 수 없다. 그러므로 앱 데이터를 모두 ui를 관리하는 activity나 fragment뿐 만 아니라, 다른 기본 구성요소가 가져서는 안 된다. 이런 ui관련 클래스는 사용자 인터페이스에 의한 로직만 가지고 있는 게 현명하다.
2. 모델에서 ui 만들기
모델을 통해 앱 데이터를 저장하고 관리하면 부드러운 사용을 할 수 있다.
3. 안드로이드 권장 아키텍쳐
따로 정리해놓은 플로우가 있음!
https://doojuns-ordinary.tistory.com/100
Android Architecture 어떻게 해야하는가?(1)
이 내용은 Android Developer내용을 읽어보면서 정리한 내용이므로, 더 자세한 내용을 알고 싶으면 공식 홈페이지에서 읽으면 됩니다!.! 우선 내가 생각했던 아키텍쳐라 함은 MVVM이니 MVI이니 MVC니 ..
doojuns-ordinary.tistory.com
엑티비티나 프레그먼트에서 옵저버블 패턴을 사용해서 데이터의 변화를 보고 이를 데이타 바인딩을 통해 뷰를 변경해 주는데 최신 컴포즈가 안정화 버전으로 나오면서, 뷰를 컴포저블 함수로 구성한다면 옵저버블 데이터를 통해 뷰를 리컴포징을 하니까 데이터 바인딩의 입지가 줄어들지 않을까 라는 생각을 해본다.
결국 ui의 일관성을 유지하기 위해서는 뷰모델을 통해서 데이터를 가지고 있으면 된다.
그런데 뷰모델의 생명주기도 엑티비티와 같이한다.
그러면 한 가지 의문이 드는데..
사용자가 앱을 종료한 경우가 아니라 안드로이드 os에서 프로세스를 종료시킨 경우에는 어떻게 앱 데이터를 유지할 수 있을까??
위의 질문에 대한 답은 Activity를 알기 위한 내용과는 다른 내용이므로 나중에 더 자세하게 알아볼 때 보아도 됨(아래)
save state handler를 사용하면 된다.
사용법은 아래의 참조 리스트에 첨부된 링크를 따라 들어가면 알 수 있다.
위의 방식을 통해서 앱을 만들면, 우려했던 것들을 막을 수 있다.
(앱 내에서 사진 등록 중 -> 전화 옴 -> 알람도 울림 -> 한참 딴 어플 보다가 다시 사진 등록하려고 함 -> 프로세스 내에서 앱 데이터 삭제해버림 -> saveStateHandler로 간단한 데이터 불러옴 EX) url ->ui 일관성 유지)
1.액티비티
액티비티는 내가 생각하기에 가장 메인이 되는 사용자 인터페이스이다.
이를 통해서 사용자와 커뮤니케이션을 하고, 앱의 시작점이라고 볼 수 있다.
우리가 어플을 켜었을 때 보이는 화면은 액티비티에 의해서 생성되고, 그게 액티비티에 의해 생성된 프래그먼트 일 수도 있다.
앞에서도 언급했지만, 안드로이드 모바일 어플은 일반적 프로그램과 달리 여러 진입점을 가지고 있으며,
서로 다른 어플끼리 진입을 할 수 있는 통로가 될 수도 있다.
그 과정은 Intent에 의해서 정의 할 수 있다.
https://doojuns-ordinary.tistory.com/109?category=1070340
1) Android Intent에 대해서
개발하면서 Intent에 대해서 많이 보게 되는데, 예제를 통해서 사용만 해 봤지 뭔지 모르고 사용한 경우가 많다. 아직 Intent에 대한 고민을 할 필요가 없거나, 다른 기본 컴포넌트들을 모른다면 몰
doojuns-ordinary.tistory.com
회원가입 중에 갤러리에 적당한 사진이 없어서 사진을 찍는 어플을 켜야 할 경우,
인텐트를 이용하여 다른 어플의 액티비티로 진입할 수 있다. 그리고 그 결과를 다시 돌려받을 수 있다.
하나의 앱이 여러 액티비티를 가질 수 있는데, 이 경우 액티비티 사이의 결합이 굉장히 느슨하다는 것을 알 수 있다.
비약이라고 볼 수 있겠는데 하나의 앱에 있는 여러 액티비티는 어떻게 보면 다른 앱이라고 볼 수도 있지 않을까?
(물론 한 앱에서 액티비티 전환을 통해서 같은 스텍에서 저장이 되고 백 스택을 통해서 데이터가 유지되는 등의 본질적인 차이는 있지만)
나는 1~2개의 액티비티에 프래그먼트 기반으로 앱을 구성하였는데,
뷰 모델을 통해서 데이터를 공유할 수 있어서 편하게 쓸 수 있는 장점이 있었다.
그러면 액티비티 간의 넘겨받는 인탠트는 중요한가? 자주 쓰는가?
인탠트는 액티비티간의 정보를 주고받는 방식이라기보다는 위에서 언급한 4대 구성요소 사이의 통신을 한다고 보면 된다.
fcm을 통해 푸시 메시지를 받을 때 인텐트를 넘겨받아서 푸시 메시지를 통해 해당 엑티비티를 띄울 수 있다.
(이 경우 Pending Intent를 제공하여 Android System이 마치 나의 어플 권한을 가지고 있는 것처럼 동작이 가능)
프래그먼트를 통해서 모든 뷰를 만들면 이러한 과정이 좀 귀찮고 자연스럽지 않은 경험이 있는데.
네비게이션을 통해서 좀 쉽게 만들 수 있다.
액티비티의 라이프사이클은 무조건 중요하다. 다른 어플을 사용하고 다시 들어올 때 그 액티비티가 Destroy된 상태인가 아니면 다시 resume으로 들어오는가 이런 것들을 알면 부드러운 사용자 인터페이스를 제공할 수 있다.
중요한 하나의 예시를 들어보자면, 어플을 켰을때 최초로 "어플이 켜졌다"라는 토스트메시지를 보여주고 싶다. 그러면 이를 어디다가 코드를 짜야하는가 onResume에 넣으면 다른 어플 켰다 들어올때도 읽어들이고, 다시 시작할때도 읽어 드린다. 그러면 최초 만들어 지는 onCreate에 사용하면 어플이 리소스 오버로 강제종료되거나 사용자가 끄지않는이상 토스트 메세지를 다시 보는 일은 없을 것이다.
2. parcelable, 번들로 데이터 주고받기
같은 프로세스 경계 전반에서 인텐트가 있는 액티비티간에 사용하고, 상태를 저장하기 위한 객체이다.
데이터를 주고받는 것에 있어서 직렬화가 가능한 Serializable이 있다.
직렬화란 객체를 바이트스트림으로 인코딩하는 것을 말하고, 네트워크라던지 다른 통신에 사용할 수 있다.
이 Serializable이란 안드로이드 SDK에는 포함되지 않지만 자바 표준 인터페이스로 데이터 클래스(pojo)에 Implement를 하여 간단하게 구현할 수 있고 이를 주고받을 수 있다. 하지만 자바 내부에서 리플렉션(바이트 스트림으로 만들고 다시 복원할 수 있도록 해줌)이 발생하고 이로 인해 많은 객체가 생성, 가비지 컬랙션이 생성되어 성능 저하를 일으킬 수 있다고 한다.
Parcelable은 안드로이드 SDK에 속하고, 인플렉션을 안 쓰고 직렬화를 하도록 도와주는 인터페이스다.
이로 인해서 설정해주는 귀찮은 과정이 있을 수 있지만, 보다 성능 좋은 방식임.
빠른 이유는 IPC에 최적화되어 있다고 하는데 자세한 건 잘 모르겠다.
근데 이는 안드로이드 SDK에 속하여 앱 -> 서버 의 통신에는 안된다.
또한 번들을 통해서도 쉽게 데이터를 넘길 수 있다.
Parcelable은 오브젝트를 넘기는 데 사용한다면,
Bundle은 그냥 map으로 구성된 상자로 데이터를 넘긴다.
마무리
어느 정도 알았다고 생각하고 봤는데, 지금 내가 구현한 앱에 부족한 부분이 보였다.
우선 뷰모델이 너무 무거운 느낌이 들었고, 객체마다의 역할이 너무 크다는 생각이 들었다.
뷰모델에서 직접 파이어 베이스에 접근하는 방식을 사용하면서 룸 데이터베이스는 원칙대로 레포지토리를 거치게 만들어져 있는데,
파이어베이스에 접근하는 것도 레포지토리에서 하도록 만들어야겠고,
인터페이스를 잘 쓰도록 노력해서 좀 더 재사용성이 좋은 방식을 찾아야겠다.
다음 글에서는 Activity의 생명주기에 대해서 자세히 알아보기러 하자
참조
https://developer.android.com/topic/libraries/architecture/saving-states
UI 상태 저장 | Android 개발자 | Android Developers
구성 변경 시 UI 상태를 유지하는 방법을 알아봅니다.
developer.android.com
'안드로이드 읽어보기 > 3. 4대 컴포넌트(Component)' 카테고리의 다른 글
3) 안드로이드 구성요소 - 서비스 (0) | 2021.11.07 |
---|---|
2) 안드로이드 구성요소 - 프래그먼트 (0) | 2021.11.06 |