버튼 수집상

[안드로이드] 싱글액티비티 구조를 언제 쓰면 좋을까? 본문

TIL - 안드로이드

[안드로이드] 싱글액티비티 구조를 언제 쓰면 좋을까?

cocokaribou 2023. 5. 23. 16:21

미리 보는 결론

UI 컴포넌트를 바꿔야할 때는 프래그먼트를 사용해서 앱 반응속도를 개선한다.
안드로이드 리소스 (비디오 플레이어, 브라우저 등)를 쓸 때는 액티비티를 사용한다.

 

필요한 스펙에 맞는 필요한 구조를 선택한다.

 

배경

현재 재직중인 회사는

MVVM 구조의 쇼핑몰 웹뷰 앱을 운영하는데,

자바에서 코틀린으로 옮기듯이

액티비티 위주의 앱을 싱글액티비티로 개선해야하지 않겠냐는 이야기가 나왔다.

 

자사에서 서비스중인 앱에

싱글액티비티 + Jetpack Navigation Component 구조가 적합할지 알아봤다.

 

1- 안드로이드 싱글액티비티를 사용해야하는 이유 (2020.5.27)

아래 글 번역 + 정리

 

Reasons to use Android Single-Activity Architecture with Navigation Component | OOZOU

Instead of having one Activity represent one screen, we view an Activity as a big container with the fragments inside the Activity representing the screen.

oozou.com

Google I/O 2018에서 발표

 

간단히 말해,

싱글액티비티 구조는 하나의 액티비티, 혹은 상대적으로 적은 수의 액티비티를 가지는 구조다.

액티비티가 하나의 화면을 나타내는 대신,

액티비티를 여러 프래그먼트를 가지는 커다란 컨테이너로 보자는 것이다.

 

- 프래그먼트로 그린 화면은 재활용이 가능하다.

UI를 액티비티 안에 프래그먼트로 그리면

그 프래그먼트를 다른 액티비티에서도 재활용할 수 있다.

하지만 액티비티 당 하나의 프래그먼트를 넣을 거면, 그냥 액티비티를 하나 쓰고 말 것이다.

 

- 액티비티에서 액티비티로 이동하는 트랜지션 애니메이션이 항상 골치였다.

최상단의 상태바가 희끄무레하게 반짝이는 것을 볼 수 있다.

물론 공식문서에서는 다루지 않는 코드를 추가해서 개선할 수 있다.

하지만 프래그먼트에서 프래그먼트로 이동하는 트랜지션에서는 이런 문제가 없다.

 

- 액티비티 간의 데이터 공유

액티비티끼리 데이터를 공유하고 싶을 때 앱 단에 (Application Scope)

싱글턴 데이터 홀더를 만든다. (* 혹은 인텐트로 전달)

하지만 앱단에는 서비스와 컨텐트 프로바이더도 접근가능하다.

싱글액티비티 구조를 사용하면

액티비티에 기반을 둔 프래그먼트 사이에서 데이터 공유가 이뤄진다.

(* activity viewmodel 로 어느 fragment에서도 접근 가능)

 

그 밖에도

- 프래그먼트에 argument를 넘길 때의 귀찮음이 줄어든다 (Safe Args Gradle Plugin)

- 딥링크 처리가 쉽다

 

그렇다면 문제점은 없는가?

만약 프래그먼트 사이에 앞뒤로 데이터를 전달하고 싶다면 어떻게 하는가?

ex) startActivityForResult

이에 관해 최근 구글에서 FragmentManager가 fragment result를 관리할 수 있게 하는 기능을 추가했다.

 

프래그먼트와 통신  |  Android 개발자  |  Android Developers

프래그먼트와 통신 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 프래그먼트를 재사용하려면 자체 레이아웃과 동작을 정의하는 완전히 독립된 구성요소

developer.android.com

새 앱을 만든다면 싱글액티비티 구조를 시도해보자.

하지만 여러 액티비티가 있는 기존 앱에 적용할 경우, 일부 흐름에 적용해보자.

ex) 로그인, 회원가입 각각의 액티비티 -> 하나의 액티비티 안에 로그인 프래그먼트, 회원가입 프래그먼트

 

 

2- 언제 액티비티 대신 프래그먼트를 쓰면 좋을까 (6년전 글)

아래 글 번역 + 정리

프래그먼트 백스택 관리에 대해 말하는 것을 보면 Jetpack AAC 발표 이전에 쓰여진 질답인 것 같다

 

When should I use Fragments over Activities in Android and why?

Answer (1 of 2): Fragment’s are, arguably, most often used to create dynamic, adaptive layouts that can accommodate various screen sizes and configurations through breaking the UI into modular units. The archetypal example involves the Master-Detail flow

www.quora.com

프래그먼트 라이프사이클은 액티비티 라이프사이클과 엮여있어서 이해하기 어려울 수 있다.

하지만 프래그먼트는 하나의 화면 안에서 부분적인 UI 요소 (modular UI elements)를 그릴 수 있고

그것이 싱글액티비티의 가장 큰 메리트이다.

 

액티비티 백스택을 관리하는 것은 여러 프래그먼트의 백스택을 관리하는 것보다 훨씬 쉽다.

액티비티 백스택은 onStop() 이후로 시스템이 관리해주기 때문이다.

하지만 프래그먼트의 백스택은 호스트 액티비티가 관리하면서 addToBackStack()을 명시적으로 호출해야만 remove 시 인스턴스를 저장한다.

그 외에도 화면돌리기 (screen orientation), 딥링킹 등도 액티비티 혹은 프래그먼트를 사용했을 때의 장단점이 존재한다.

 

하지만 액티비티를 쓸지, 프래그먼트를 쓸지는

결국 앱의 요구사항과 앱 네비게이션에 따라야 한다.

글쓴이가 토이프로젝트로 만든 장보기 리스트 앱같은 경우,

사이드 drawer로 이동하는 구조이기 때문에 싱글액티비티 + 여러 프래그먼트가 적합하다.

 

샘플 코드

위 글들을 염두에 두고

Jetpack Navigation Component를 써서 간단한 앱을 만들어봤다.

 

GitHub - cocokaribou/android_projects: A repository for android projects🤖

A repository for android projects🤖. Contribute to cocokaribou/android_projects development by creating an account on GitHub.

github.com

화면이동 로직만 자사 앱의 요구사항을 반영해서 구현해봤다.

destination 을 선언해두면 프래그먼트의 add, remove를 신경쓰지 않아도 되는 점이 확실히 편했다.

하지만 화면 이동과 데이터 처리가 결합됐을 때 원하는대로 처리하기가 어려웠다.

아마도 아직 네비게이션 기능 숙지가 덜 된 탓이다.

 

정리

프래그먼트 스택 관리는 네비게이션 도입으로 개선될 수 있다.

 

싱글액티비티 구조는 하나의 기능을 수행하면서 여러 네이티브 화면을 이동하는 앱에 적합하다.
    - ex) 가계부, TODO list

 

쇼핑몰 웹뷰 앱은 웹사이트처럼 동작하기를 기대하고 기능이 다양하다.
    - ex) 브라우저, 웹앱 연동, 비디오 전체화면 등등


또한 화면이동과 데이터 처리가 연계되어있는 경우가 있다.
    - ex) 상품상세로 이동하거나 뒤로가기 시 스크립트 호출, activity result로 처리되는 데이터

 


현재로선

웹 기반의 쇼핑몰 앱을 싱글 액티비티로 바꿀 이유가 딱히 없어보인다.

더 알아보게 되면 아래에 추가로 달겠다.

728x90