본문 바로가기
Study

안드로이드 권장 아키텍처

by ca.rrot 2022. 7. 26.

목차.

1. 앱 개발자가 직면한 문제
2. 일반 아키텍처 원칙
3. 권장 앱 아키텍처
4. 구성요소 간 종속 항목 관리
5. 일반 권장사항

 

본 포스팅은 안드로이드 공식 사이트의 앱 아키텍처 가이드 문서를 바탕으로 작성되었습니다.

 

 

 

앱 개발자가 직면한 문제

공식 문서에서 가장 먼저 나와있는 키워드는 ‘모바일 앱 사용자 환경'입니다.

 

우리가 평소에 핸드폰을 이용할 때를 떠올려 보겠습니다. 여러 가지 앱을 왔다 갔다 이동하면서 사용하거나, 앱 이용 중에 전화가 오거나, 앱 안에서 사진 선택 기능을 이용하며 갤러리로 이동하거나… 등 우리는 앱을 사용하면서 한 곳에만 머물러 있지 않습니다. 이러한 환경을 모바일 앱 사용자 환경이라고 보시면 됩니다.

 

앱은 일반적인 데스크탑과 달리 훨씬 복잡한 구조를 가지고 있습니다. 일반적인 안드로이드 앱은 Activity, Fragment, Service, Content Provider, Bradcase Receiver를 비롯하여 여러 구성요소가 포함됩니다.

또한 휴대기기는 리소스가 제한되어 있으므로, 운영체제에서 새로운 앱을 위한 공간을 확보하도록 언제든지 일부 앱 프로세스를 종료해야 할 수 있습니다.

 

위 여러 가지 환경을 고려해 봤을 때,

사용자는 짧은 시간 내에 여러 앱과 상호작용하는 경우가 많기 때문에 사용자 중심의 다양한 워크플로 및 작업에 맞게 조정될 수 있어야 합니다.

 

앱 구성요소는 개별적이고 비 순차적으로 실행될 수 있으며, 운영체제나 사용자가 언제든지 앱 구성요소를 제거할 수 있습니다. 이러한 이벤트는 직접 제어할 수 없기 때문에 앱 구성요소에 애플리케이션 데이터나 상태를 저장해서는 안 되며 앱 구성요소가 서로 종속되면 안 됩니다.

 

그렇다면 어떻게 앱을 어떻게 설계해야 할까요?

 

일반 아키텍처 원칙

관심사 분리(Seperation Of Concern)

관심사 분리(SoC)는 컴퓨터 프로그램을 구별된 부분으로 분리시키는 디자인 원칙으로 하나의 관심사에서 하나의 역할만 가지도록 구성하는 것입니다. 관심사가 잘 분리됐을 때 유지 보수, 재사용 등을 위한 자유도가 높아집니다.

 

Activity 및 Fragment에 모든 코드를 작성하는 실수를 하면 안 됩니다. 해당 클래스는 최대한 가볍게 유지해야 많은 수명 주기 관련 문제를 피할 수 있습니다. 이러한 클래스는 사용자의 터치나 메모리 부족과 같은 이유로 언제든지 OS에서 제거될 수 있기 때문입니다. 견고한 사용자 환경을 제공하려면 의존성을 최소화하고 각각의 관심사를 분리하여 코드를 작성해야 합니다.

 

데이터 모델에서 UI 도출하기

또 하나의 중요한 원칙은 지속성 있는 모델로 UI를 구동해야 한다는 것입니다.

 

지속성 있는 모델이 이상적인 이유입니다.

  • Android OS에서 리소스를 확보하기 위해 앱을 제거해도 사용자 데이터가 삭제되지 않습니다.
  • 네트워크 연결이 취약하거나 연결되어 있지 않아도 앱이 계속 작동합니다.

데이터 모델은 앱의 데이터 처리를 담당하며, 앱의 View 객체 및 구성요소로부터 독립되어 있습니다. 따라서 앱의 수명 주기 관련 문제에 영향을 받지 않습니다. 

 

잘 정의된 데이터 모델 클래스에 기반하는 경우 앱을 쉽게 테스트하고 일관성 있게 유지할 수 있습니다.

 

권장 앱 아키텍처

각 Android 앱에는 최소한 다음 두 가지 계층이 있어야 합니다.

  • 화면에 애플리케이션 데이터를 표시하는 UI 계층
  • 앱의 비즈니스 로직을 포함하고 애플리케이션 데이터를 노출하는 데이터 계층

도메인 계층이라는 추가 계층을 더해 UI 계층과 데이터 계층 간의 상호 작용을 단순화하고 재사용할 수 있습니다.

 

일반적인 앱 아키텍처 다이어그램

 

 

UI 레이어

UI 레이어의 역할은 화면에 애플리케이션 데이터를 표시하고 사용자 상호작용의 기본 지점으로서의 역할을 수행하는 것입니다. 

앱 데이터의 변경사항을 UI가 표시할 수 있는 형식으로 변환해 표시해 주는 파이프라인 역할을 합니다.

앱 아키텍처에서 UI 레이어의 역할

UI Layer는 두 가지로 구성됩니다.

UI elements : UI 요소 / 공식 문서에서는 Jetpack Compose를 소개하고 있습니다.

State holder - UI 상태 / 예로는 ViewModel이 있습니다.

UI는 화면에 있는 UI 요소와 UI 상태를 결합한 결과

 

 

데이터 레이어

데이터 레이어에는 비즈니스 로직이 포함되어 있으며, 데이터 소스를 포함할 수 있는 저장소(Repository) 형태로 구성됩니다.

각 데이터 소스 클래스는 파일, 네트워크 소스, 로컬 데이터베이스 같은 하나의 데이터 소스만 사용해야 합니다. 데이터 소스 클래스는 데이터 작업을 위해 애플리케이션과 시스템 간의 가교 역할을 합니다

 

비즈니스 로직 : 앱에 가치를 부여하는 요소로, 애플리케이션의 데이터 생성, 저장, 변경 방식을 결정하는 실제 비즈니스 규칙으로 구성됩니다.

앱 아키텍처에서 데이터 레이어의 역할

 

 

도메인 레이어

도메인 레이어는 UI와 데이터 레이어 사이의 선택적 레이어입니다. 복잡성을 처리하거나 재사용성을 선호하는 등 필요한 경우에만 사용합니다. 복잡한 비즈니스 로직, 또는 여러 ViewModel에서 재사용되는 비즈니스 로직의 캡슐화를 담당합니다.

앱 아키텍처에서 도메인 레이어의 역할

 

 

구성요소 간 종속 항목 관리

특정 클래스의 종속 항목을 수집하는 데 종속 항목 주입(DI), 서비스 로케이터 패턴 중 하나를 사용할 수 있습니다.

 

  • 종속 항목 주입(DI): 종속 항목 주입을 사용하면 클래스가 자신의 종속 항목을 구성할 필요 없이 종속 항목을 정의할 수 있습니다. 런타임 시 다른 클래스가 이 종속 항목을 제공해야 합니다.
  • 서비스 로케이터: 서비스 로케이터 패턴은 클래스가 자신의 종속 항목을 구성하는 대신 종속 항목을 가져올 수 있는 레지스트리를 제공합니다.

이 패턴은 코드를 중복하거나 복잡성을 추가하지 않아도 종속 항목을 관리하기 위한 명확한 패턴을 제공하므로 코드를 확장할 수 있습니다. 또한 이러한 패턴을 사용하면 테스트와 프로덕션 구현 간에 신속하게 전환할 수 있습니다.

 

공식 문서에서는 종속 항목 삽입 패턴을 따르고 Hilt 라이브러리를 사용하는 것을 권장합니다.

Hilt는 Android에서 종속 항목 삽입을 위한 Jetpack의 권장 라이브러리입니다. Hilt는 프로젝트의 모든 Android 클래스에 컨테이너를 제공하고 수명 주기를 자동으로 관리함으로써 애플리케이션에서 DI를 실행하는 표준 방법을 정의합니다.

Hilt는 Dagger가 제공하는 컴파일 타임 정확성, 런타임 성능, 확장성 및 Android 스튜디오 지원의 이점을 누리기 위해 인기 있는 DI 라이브러리 Dagger를 기반으로 빌드 되었습니다.

 

 

일반 권장사항

아래 권장사항은 필수는 아니지만, 장기적으로 더 강력하고, 테스트 및 유지관리가 쉬운 코드 베이스를 만들 수 있습니다.

 

앱 구성요소에 데이터를 저장합니다.
활동, 서비스, broadcast receiver와 같은 앱의 진입점을 데이터 소스로 지정하지 마세요. 대신 그 진입점과 관련된 데이터 일부만 가져오도록 다른 구성요소에 맞춰 조정해야 합니다. 각 앱 구성요소는 사용자와 기기의 상호작용 및 시스템의 전반적인 현재 상태에 따라 매우 단기간만 지속됩니다.

Android 클래스의 종속 항목을 줄입니다.
앱 구성요소는 Context 또는 Toast 같은 Android 프레임워크 SDK API를 사용하는 유일한 클래스여야 합니다. 앱 구성요소와 별도로 앱의 다른 클래스를 추상화하면 테스트 가능성은 높이고 앱 내의 커플링은 줄일 수 있습니다.

앱의 다양한 모듈 간 책임이 잘 정의된 경계를 만듭니다.
예를 들어 네트워크에서 데이터를 로드하는 코드를 코드베이스의 여러 클래스나 패키지 전체에 분산하면 안 됩니다. 마찬가지로 데이터 캐시와 데이터 결합 등 여러 개의 관련 없는 책임을 동일한 클래스에 정의하면 안 됩니다. 권장 앱 아키텍처를 따르면 여기에 도움이 됩니다.

각 모듈에서 가능하면 적게 노출합니다.
예를 들어 모듈의 내부 구현 세부정보를 노출하는 단축키를 만들어서는 안 됩니다. 단기적으로는 약간의 시간을 벌 수 있지만, 코드베이스가 발전함에 따라 기술적 문제가 여러 번 발생할 수 있습니다.

다른 앱과 차별되도록 앱의 고유한 핵심에 초점을 맞춥니다.
동일한 상용구 코드를 반복하여 작성하느라 시간을 낭비하지 마세요. 대신 앱을 독특하게 만드는 데 시간과 에너지를 집중하고 반복적인 상용구는 Jetpack 라이브러리와 기타 권장 라이브러리가 처리하도록 하세요.

앱의 각 부분을 독립적으로 테스트하는 방법을 고려합니다.
예를 들어 네트워크에서 데이터를 가져오기 위해 API를 잘 정의하면 해당 데이터를 로컬 데이터베이스에 보존하는 모듈을 더 쉽게 테스트할 수 있습니다. 그러지 않고 두 모듈의 로직을 한 위치에 혼합하거나, 네트워크 코드를 전체 코드베이스에 분산하면 효과적인 테스트가 불가능하지는 않을지라도 훨씬 더 어려워집니다.

가능한 한 관련성이 높은 최신 데이터를 보존합니다.
이렇게 하면 기기가 오프라인 모드일 때도 사용자가 앱의 기능을 이용할 수 있습니다. 모든 사용자가 끊김 없고 속도가 빠른 연결을 사용하지는 않는다는 점에 유의하세요. 끊김 없고 속도가 빠르더라도 혼잡한 곳에서는 수신 상태가 좋지 않을 수 있습니다.

 

 

 

 

 

 

'Study' 카테고리의 다른 글

디자인 패턴  (2) 2022.07.21
안드로이드 APK 구조  (0) 2022.07.06
안드로이드 OS 구조  (0) 2022.07.04
구글 안드로이드 역사  (0) 2022.06.29

댓글