-
모바일 앱 사용자 환경
- 앱 구성요소는 Activity, Fragment, Service, ContentProvider, Broadcast Receiver 가 있다.
- 휴대기기 리소스가 제한되어있기 때문에 앱을 위한 공간을 확보하고 언제든지 일부 앱 프로세스가 종료 될 수 있다.
- 앱 구성 요소는 개별적이고 비순차적으로 실행될 수 있으며, 운영체제에 의해 앱이 소멸 될 수 있다. 이러한 이벤트는 직접 제어할 수 없기 때문에 앱 구성요소에 애플리케이션 데이터나 상태를 저장해서는 안 되며 앱 구성요소가 서로 종속 되면 안된다.
-
일반 아키텍처 원칙
- 애프리케이션의 데이터와 상태를 저장하고 앱 구성요소를 사용할 수 없기 때문에 앱 아키텍처가 필요하다. 앱 아키텍처는 각 기능 간의 경계를 정의하여 앱을 견고하게 만든다.
-
관심사 분리
- Activity와 Fragment와 같은 UI 기반 클래스는 UI 및 운영체제 상호작용을 처리하는 로직만 포함해야한다. 이렇게 코드를 가볍게하여 구성요소와 수명 주기와 관련된 많은 문제를 피하고 클래스 테스트 기능성을 개선할 수 있다.
- Activity 및 Fragment 구현은 소유 대상이 아니고 Android OS와 앱 사이의 계약을 나타내도록 이어주는 클래스이다. OS에 의해 언제든지 소멸될 수 있기 때문에 이러한 클래스에 대한 의존성을 최소화 하는 것이 좋다.
-
데이터 모델에서 UI 도출하기
- 데이터 모델은 앱의 데이터를 나타내며 UI의 구성요소와 독립되어 있다. UI 및 앱의 구성요소 수명주기와 관련이 없다. 하지만 OS가 메모리에서 앱의 프로세스를 삭제하면 데이터 모델도 삭제된다.
- 지속 모델이 이상적인 이유: Android OS 에서 앱을 제거해도 사용자 데이터가 삭제되지 않는다.
- 네트워크 연결이 취약하거나 연결되지 않아도 앱이 계속 작동한다.
-
단일 소스 저장소
- 앱에서 새로운 데이터 유형을 정의할 때 데이터 유형에 단일 소스 저장소를 할당해야한다. (SSOT)
SSOT는 데이터 소유자 이며 SSOT만 데이터를 수정 변경할 수 있다.
SSOT는 이를 위해 불변 유형(val)을 사용하여 데이터를 노출하고 다른 유형이 호출할 수 있는 이벤트를 수신하거나 함수를 노출하여 데이터를 수정한다.
- SSOT 패턴의 이점
- 특정 유형 데이터의 모든 변경사항을 한곳으로 일원화한다.
- 다른 유형이 조작할 수 없도록 데이터를 보호한다.
- 데이터 변경사항을 더 쉽게 추적할 수 있도록한다. (버그 발견에 유용)
오프라인 중심의 애플리케이션의 데이터 정보소스는 주로 데이터베이스이다. 정보 소스가 ViewModel이거나 UI인 경우도 있다.
-
단방향 데이터 흐름
- 단일 소스 저장 원칙은 Google 가이드에서 종종 단방향 데이터 흐름(UDF)패턴과 함께 사용 된다. UDF에서 상태는 한방향으로 흐르고, 데이터를 수정하는 이벤트는 반대 방향으로 흐른다.
- 앱에서 상태 또는 데이터는 일반적으로 계층 구조의 상위 범위 유형에서 하위 범위 유형으로 흐른다.
반대로 이벤트는 보통 하위 범위 유형에서 트리거되어 상응하는 데이터 유형의 SSOT(단일 소스 저장소)에 도달한다.
이 패턴은 데이터 일관성을 강화하고, 오류 발생 확률을 줄여주며 디버그를 쉽게한다.
-
권장 앱 아키텍처
-
화면에 애플리케이션 데이터를 표시하는 UI 레이어
-
앱의 비지니스 로직을 포함하고 애플리케이션 데이터를 노출하는 데이터레이어
화살표는 클래스 간의 종속성을 나타낸다
-
최신 앱 아키텍처
- 반응형 및 계층형 아키텍처
- 앱의 모든 레이어에서의 단방향 데이터 흐름 (UDF)
- 상태 홀더가 있는 UI 레이어로 UI의 복잡성 관리
- 코루틴 및 흐름
- 종속 항목 삽입 권장사항
-
UI 레이어
- UI는 화면에 데이터를 표시한다. 사용자의 상호작용(버튼 클릭) 또는 외부 입력(네트워크 응답)으로 인해 데이터가 변할 때 마다 변경 사항을 반영하여 UI가 업데이트 되야한다.
- 화면에 데이터를 렌더링하는 UI 요소 (View, Jetpack Compose 함수)
- 데이터를 보유하고 이를 UI에 노출하며 로직을 처리하는 상태 홀더(ViewModel 클래스)

-
데이터 레이어
- 데이터 레이어에는 비지니스 로직이 포함되어있다. 비지니스 로직은 앱에 가치를 부여하는 요소로 데이터의 생성 저장 변경 방식을 결정하는 규칙으로 구성된다.
- 데이터 레이어는 0개 부터 여러개의 데이터 소스를 각각 포함할 수 있는 저장소로 구성된다. 예를 들어 영화관련 데이터에는 MoviesRepository 클래스, 결제관련 데이터에는 PaymentsRepository 클래스를 만들 수 있다.

- 저장소 클래스에서 담당하는 작업
- 앱의 나머지 부분에 데이터 노출
- 데이터 변경 사항을 한곳에 집중
- 여러 데이터 소스간의 충돌 해결
- 앱의 나머지 부분에서 데이터 소스 추상화
- 비지니스 로직 포함
-
도메인 레이어 (Optional Layer)
- 복잡한 비지니스 로직이나 여러 ViewModel에서 재사용되는 간단한 비지니스 로직의 캡슐화를 담당한다. 예를들어 ViewModel에서 시간대를 사용하여 적절하게 화면에 메시지를 표시할 수 있는 GetTimeZoneUseCase 클래스가 있다.
-
구성요소 간 종속 항목 관리
앱의 클래스는 올바른 동작을 위해 다른 클래스에 종속된다. 아래 패턴중 하나를 사용할 수 있다.
- 종속 항목 주입(DI): 종속 항목 주입을 사용하면 클래스가 자신의 종속 항목을 구성할 필요 없이 종속 항목을 정의할 수 있다. 런타임 시 다른 클래스가 이 종속 항목을 제공해야한다.
- 서비스 로케이터: 서비스 로케이터 패턴은 클래스가 자신의 종속 항목을 구성하는 대신 종속 항목을 가져올 수 있는 레지스트리를 제공한다.
-
일반 권장사항
- 앱 구성요소에 데이터를 저장한다.: 활동 서비스 BroadcastReceiver와 같은 앱 진입점을 데이터 소스로 지정하지 않는다. 대신 그 진입점과 관련된 데이터 일부만 가져오도록 구성요소에 맞춰 조정한다.
- Android 클래스의 종속 항목을 줄인다: 앱 구성요소는 Context 또는 Toast 같은 Android 프레임웤SDK API 를 사용하는 유일한 클래스여야한다.
- 앱의 다양한 모듈 간 책임이 잘 정의된 경계를 만든다.:
- 각 모듈에서 가능한 적게 노출한다.
- 다른 앱과 차별되도록 앱의 고유한 핵심에 초점을 맞춘다.
- 앱의 각 부분을 독립적으로 테스트 하는 방법을 고려한다.: 네트워크와 로컬 데이터베이스에서 데이터를 가져오기위한 API를 잘 정의하면 데이터 보존 모듈을 더 쉽게 테스트 할 수 있다.
- 유형은 동시 실행 정책을 담당한다.
- 가능한 관련성이 높은 최신 데이터를 보존한다.
-
아키텍처의 이점
- 앱의 전반적인 유지관리성, 품질, 견고성이 개선된다
- 앱을 확장할 수 있다. 코드 충돌이 최소화되어더 많은 팀이 동일한 코드베이스에 기여할 수 있다.
- 온보딩에 도움이된다.(코드의 일관성)
- 테스트가 쉽다.
- 버그를 체계적으로 조사할 수 있다.