Android App에는 Activity, Fragment, Services,Content Providers, Broadcast receiver를 비롯한 여러 앱 컴포넌트가 포함됩니다. Menifest에 이러한 구성 요소 대부분을 선언합니다.
일반적인 Android App은 여러 구성 요소를 포함할 수 있고, 여러 앱과 상호작용(카메라 등)할 때도 많다는 점을 고려하여 다양한 워크플로우 및 작업에 맞게 조정될 수 있어야 합니다.
또한 리소스가 제한되어 있기에 OS가 새로운 공간 확보를 위해 언제든지 App 프로세스를 종료 가능해야 합니다.
결론적으로 App 구성 요소는 개별적, 비순차적으로 실행될 수 있으며, OS, 사용자가 언제든지 구성 요소를 소멸시킬 수 있습니다. 이러한 이벤트는 직접 제어 불가능하기에 구성 요소에 데이터나 상태를 저장해선 안되며 각 구성 요소가 종속되면 안됩니다.
구성 요소에 데이터 혹은 상태를 저장하면 안된다고 설명했습니다. 그렇다면 어떻게 앱을 설계해야할요?
가장 중요한 원칙 중 하나인 관심사 분리입니다. Activity 또는 Fragment에 모든 코드를 작성해도 될까요?
UI 기반의 클래스인 Activity와 Fragment의 관심사는 UI 및 OS 상호작용을 처리하는 로직만 포함되어야 합니다. 이렇게 작성된 class는 가볍게 유지 가능하며 LifeCycle과 관련된 많은 문제를 피하며 테스트 가능성을 개선할 수 있습니다.
Activity와 Fragment는 다양한 조건(메모리 부족, 사용자 상호작용 등)으로 OS에 의해 소멸될 수 있습니다. 만족스러운 사용자 환경과 수월한 앱 관리 환경을 제공하려면 이러한 클래스에 대한 의존성을 최소화해야 합니다.
또 하나의 중요한 원칙은 데이터 모델에서 UI를 도출해야 한다는 것입니다. 데이터 모델은 앱의 데이터를 나타냅니다. 데이터 모델은 앱의 비즈니스 로직과 사용자 인터페이스 간의 데이터 흐름을 관리하는 데 사용합니다.
MVC, MVVM 패턴을 이야기 할 때 Model 부분에 해당합니다.
이러한 모델은 핵심 데이터를 표현하고 관리하는 역할을 합니다.

코틀린의 data class를 활용하여 data model을 만든 예입니다.
데이터 모델은 UI 및 구성요소와는 독립되어 있으며 LifeCycle과도 관련이없으며 지속적인 모델을 설계하도록 해야 합니다.
앱에서 새로운 데이터 타입을 정의할 때 데이터 타입에 단일 소스 저장소(Single Source of Truth)를 할당해야 합니다. 여기서 단일 소스 저장소는 무엇을 의미하는 것일까요?
SSOT는 데이터를 단일하고 일관된 소스에서 가져오고 유지하는 원칙을 나타냅니다.
이것은 데이터의 일관성과 중복을 방지하며 앱의 데이터를 관리하는 효과적인 방법을 제공합니다.
일반적으로 안드로이드 앱에선 Room 라이브러리와 함께 사용되어 로컬 데이터베이스를 나타내며, SSOT의 구현에 기여하게 됩니다.
@Entity
data class User(
@PrimaryKey val id: Int,
val name: String,
val email: String
)
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAllUsers(): LiveData<List<User>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(user: User)
}
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
User는 데이터 모델을, Dao는 데이터베이스와 상호 작용하는 메서드를 정의합니다. AppDatabase 클래스는 RoomDatabase를 확장하며, 앱의 데이터베이스를 정의합니다.
이러한 구조를 통해 데이터베이스가 SSOT의 역할을 하며, 앱의 다양한 구성 요소에서 데이터를 가져오고 업데이트할 수 있습니다.
SSOT 패턴은 다음과 같은 이점을 제공합니다.
SSOT는 단방향 데이터 흐름(UDF) 패턴과 함께 사용됩니다. UDF에서 상태는 한 방향으로만 흐릅니다. 데이터를 수정하는 이벤트는 반대 방향으로 흐릅니다.
안드로이드에서 상태 또는 데이터는 계층 구조의 상위 유형에서 하위 유형으로 흐릅니다. 이벤트는 하위 유형에서 트리거되어 상응하는 유형의 SSOT에 도달합니다.
앱 데이터는 데이터 소스에서 UI로, 버튼 클릭 이벤트와 같은 사용자 이벤트는 UI에서 SSOT로 흐르게 되며 이때 데이터는 불변으로 수정 및 노출됩니다.
또한 안드로이드에서는 Jetpack 라이브러리의 ViewModel과 LiveData를 사용해 이러한 패턴을 구현할 수 있습니다.
다음 섹션에선 Android Developers 공식 문서에서 권장하는 앱 아키텍처와 구조화 하는 방법에 대해 알아보겠습니다.
참고 문서