성장기록지

android 권장 아키텍쳐란? 본문

안드로이드

android 권장 아키텍쳐란?

pengcon 2025. 1. 2. 15:41
프로젝트 진행할 때 적용하였던 클린아키텍쳐를 설명하기 위해선
먼저 안드로이드 권장 아키텍쳐를 설명하는것이 좋다고 생각하여서
정리하는 글을 작성해보고자 한다.

 

 

일반적인 아키텍처 원칙

앱 아키텍처는 앱의 부분과 그 각 부분에 필요한 기능 간의 경계를 정의하는 것이다. 

따라서 몇가지 특정 원칙을 준수하여야 한다.

1. 관심사 분리

Activity,Fragment와 같은 UI 기반 클래스에는 UI 및 운영 체제 상호 작용을 처리하는 로직만 포함하여야 하는 것처럼

각자의 관심사에 맞게 책임을 가진 코드를 분리하여야 함을 의미한다.

Activity와 Fragment는 OS와 애플리케이션을 이어주는 클래스이므로, 메모리부족과 같은 경우에 프로세스 킬이 일어날 수 있다. 따라서 관심사 분리 없이 해당 컴포넌트에 모든 코드를 넣게되면 많은 문제가 생길 수 있다.

2. 데이터 모델에서 UI 도출

 화면에 보여질 UI를 먼저 정한 다음 어떤 데이터들이 필요할지를 정하는 것이 아니라, 데이터 모델에서 UI를 도출해야 한다. 데이터 모델은 앱의 데이터를 나타내며, 앱의 UI 요소 및 기타 구성요소로부터 독립되어 있다. 즉, 이들은 UI 및 앱 구성요소 수명 주기와는 관련이 없다. 

3. 단일 소스 저장소(SSOT)

앱에서 새로운 데이터 유형을 정의할 때는 데이터 유형에 단일 소스 저장소를 할당해야 한다.

 SSOT는 데이터의 소유자이며, SSOT만 데이터를 수정하거나 변경할 수 있다. SSOT는 이를 위해 불변 유형을 사용해 데이터를 노출하며, 다른 유형이 호출할 수 있는 이벤트를 수신하거나 함수를 노출해 데이터를 수정한다.

 

이 패턴에는 여러 가지 이점이 있다.

  • 특정 유형 데이터의 모든 변경사항을 한곳으로 일원화한다.
  • 다른 유형이 조작할 수 없도록 데이터를 보호한다.
  • 데이터 변경사항을 더 쉽게 추적할 수 있도록 한다. 따라서 버그를 발견하기가 쉽다.

요약하자면  데이터를 안전하게 보호하기 위해 다른 클래스에서 수정할 수 없도록 하라는 뜻이다.

아래와 같은 Backing Property등으로 ssot를 구현할 수 있다.

class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<String>() // 비공개 데이터 (백킹 프로퍼티 역할)
    val data: LiveData<String> = _data // 공개적으로 노출되는 SSoT

    fun updateData(newData: String) {
        _data.value = newData
    }
}

 

 

오프라인 중심 애플리케이션의 애플리케이션 데이터 정보 소스는 주로 데이터베이스이다.

정보 소스가 ViewModel이거나 UI인 경우도 있다.

4. 단방향 데이터 흐름 (Unidirectional Data Flow)

단방향 데이터 흐름이란?
이름에서도 알 수 있다시피, 데이터가 오로지 한 방향으로만 흐르는 것을 의미한다.

Up Stream방식과 'Down Stream' 방식이 있다.

 

안드로이드 권장 아키텍쳐에서의 UDF

  • Up Stream : 사용자가 클릭 등의 이벤트를 발생시킴으로써 Ui -> Domain -> Data로 전달함으로써 상위 레이어로 전달하는 방식
  • Down Stream : Remote or Local Server로부터 받은 데이터를 Data -> Domain -> Ui로 전달함으로써 하위 레이어로 전달하는 방식

 

android 권장 아키텍쳐

안드로이드에서 권장하고 있는 앱 아키텍처의 구조는 위의 그림과 같다.

UI 레이어와 Data 레이어는 필수이고 , Domain Layer는 선택사항이다. 

 

UI와 데이터 레이어 간의 상호작용을 간소화하고 재사용하기 위해 도메인 레이어를 추가할 수 있다.

 

UI Layer 

UI LAYER는

화면에 데이터를 렌더링하는 UI 요소(Activity,Fragment,ContsraintLayout 등..) 와

데이터를 보유하고 이를 UI에 노출하며 로직을 처리하는 State Holders(viewmodel) 로 이루어져 있다.

요약하자면 다음과 같다. 

  • ViewModel이 UI에 사용될 상태를 보유하고 노출. UI 상태는 ViewModel에 의해 변환된 애플리케이션 데이터이다.
  • UI가 ViewModel에 사용자 이벤트를 알린다.
  • ViewModel이 사용자 작업을 처리하고 상태를 업데이트한다.
  • 업데이트된 상태가 렌더링할 UI에 다시 제공된다.
  • 상태 변경을 야기하는 모든 이벤트에 위의 작업이 반복된다

[UI Elements]

  • UI상태 자체를 나타낸다. (TextView, ConstraintLayout, ComposeUI...)

[ViewModel의 책임]

  • UpStream관점에서 사용자의 이벤트를 받아 비즈니스 로직을 시작시키는 책임
  • DownStream관점에서 상위 레이어로부터 받은 데이터를 UI에 바인딩해주는 책임
  • UI에 바인딩해준 데이터를 상태 홀더 클래스(LiveData or StateFlow)를 통해 보유한다.

 

 

Data Layer

위에서 언급되었던 데이터 레이어에 관해 알아보자

데이터 레이어에는 비즈니스 로직이 포함되어 있다. 비즈니스 로직은 앱에 가치를 부여하는 요소로, 앱의 데이터 생성, 저장, 변경 방식을 결정하는 규칙으로 구성된다.

 

데이터 레이어는 Repository, Data Source로 이루어져있다.

데이터 레이어의 진입점은 항상 Repository 클래스여야 하고, 이 레이어에서 노출된 데이터는 변경 불가능해야 한다.

Data Source  클래스는 데이터 작업을 위한 애플리케이션과 시스템 간의 가교 역할을 한다.

 

데이터 레이어는 각각 0개에서 많은  Data Source를 포함할 수 있는 Repository로 구성된다.

앱에서 처리하는 각기 다른 데이터 유형에 대해 Repository 클래스를 만들어야 한다.

 

 

[Repository]

  • UpStream관점에서 앱 내 필요 데이터를 DataSource에 요청하는 책임
  • DownStream관점에서 DataSource로부터 받아온 데이터를 새로운 모델로 가공하여 하위 레이어(Domain or Ui)에 전달해주는 책임
  • 가공한 데이터를 Repository모듈에 캐싱하는 책임

[DataSource]

  • UpStream관점으로 Remote or/and Local Server에 데이터를 요청한다.
  • DownStream관점으로 Repository에 데이터를 제공한다.

정리하자면 , DataSource는 Remote or Local Server로부터 받은 데이터를 1차 생산자로 제공해주는 모듈이라고 볼 수 있고, Repository는 DataSource로부터 받은 데이터를 하위 레이어(Domain or UI)에 제공해주는 2차 생산자의 역할이라고 볼 수 있다.

 

Domain Layer (선택사항)

  • UseCase가 해당하는 모듈이다.
  • 복잡한 비즈니스 로직이나 여러 ViewModel에서 재사용되는 간단한 비즈니스 로직의 캡슐화를 담당한다.
  • 따라서 복잡성을 처리하거나 재사용성을 선호하는 등 필요한 경우에만 도메인 레이어를 사용해야 한다.

 

 

 

참고 자료

https://everyday-develop-myself.tistory.com/208

https://velog.io/@squart300kg/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Clean-Architecture%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC