앱 아키텍처 정보 > 권장 앱 아키텍처

John·2023년 6월 22일
0

UI(Presentation) Layer

Presentation 영역에서는 말 그대로 렌더링에 대한 책임을 가집니다.
일반적인 View 또는 Jetpack Compose 를 사용해요.
Presentation 영역에서는 보통 MVVM 또는 MVI 패턴 등을 이용하여,
이 레이어 내부에서의 역할과 책임을 다시 구분합니다.

Domain Layer

도메인 레이어는 UI 레이어와 데이터 레이어 사이에 있는 선택적 레이어입니다.
도메인 레이어는 복잡한 비즈니스 로직이나 여러 ViewModel에서 재사용되는 간단한 비즈니스 로직의 캡슐화를 담당합니다. 모든 앱에 이러한 요구사항이 있는 것은 아니므로 이 레이어는 선택사항입니다. 따라서 복잡성을 처리하거나 재사용성을 선호하는 등 필요한 경우에만 도메인 레이어를 사용해야 합니다.

아마도 공식 문서에서 Domain Layer 를 '선택적'이라고 권한 것은,
Data 영역의 Repository 구현체와 Domain 영역의 UseCase 둘 중의 하나가 굉장히 보일러플레이트로 보일 수 있기 때문이지 않을까 싶어요.

실제로, Remote 데이터를 가져와서 화면에 그려주는 단순한 화면을 구현할 때는, UseCase 와 Repository 가 단순히 가교 역할만 할 때가 많죠.
각 영역을 횡단하느라 불필요하게 Mapper 만 열심히 만들고 있는 나를 발견할 때가 있긴 했습니다.

그럼에도, 프로젝트의 특정 기능은 언제든지 '복잡'해질 수 있고,
여러명이 참여하는 경우 전체적인 아키텍처의 '가독성/통일성'을 위해서,
Domain Layer 는 항상 준비해두는 게 좋을 것 같습니다.

Data Layer

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

Data Layer 에 비즈니스 로직을 포함하는 것에는 개인적으로 반대입니다.
핵심 업무 규칙 등의 비즈니스 로직은 역시 Domain 에 집중되는 것이 좋겠습니다.

따라서, Data Layer 에서는 각각의 DataSource 로 접근할 수 있는 Repository 구현체를 만들어줘야하고,
SSOT 를 실현시키기 위한, 책임을 가져야하겠습니다.

일반 권장사항

앱 구성요소에 데이터를 저장합니다.

공식 문서 한글 번역 오류네요.

Don't store data in app components.

앱 구성요소는 Android Components 를 뜻한다고 봐요.
Android 의 4대 컴포넌트 중 Activity, Service, Broadcast Receiver 에서 데이터를 저장하는 일을 피해야합니다.
시스템의 상황에 따라, 언제든 우리의 통제를 벗어날 수 있기 때문이죠.

Android 클래스의 종속 항목을 줄입니다.

Android 개발은 Android 플랫폼에 의존적일 수 밖에 없습니다.
그럼에도, 의존성을 최소한으로 줄이는 노력은 분명,
유지/보수/가독성 등에 도움이 됩니다.
Activity 또는 Fragment 와 같은 Android Component 에서 최대한 Android API 를 활용하고, Android Component 가 아닌 곳에서는 사용을 지양해야합니다.

LocalDatasource 로 Android SQLite(android.database.sqlite) 를 사용한다고 가정할 때, Local Datasource 인터페이스는 Data Layer 에 위치하고, Local Datasource 구현체는 아마도, main 영역에 따로 둬야할 것 같습니다. Data Layer 에서 Android 의존성이 생기는 것은 피해야하니까요.
어떤 구현체가 Android 의존성이 생길 때에 대해서 조금 더 고민해봐야겠어요.

앱의 다양한 모듈 간 책임이 잘 정의된 경계를 만듭니다.

SRP는 함수, 클래스를 넘어서 모듈간에도 적용되어야 하죠.

각 모듈에서 가능하면 적게 노출합니다.

Interface 를 활용해서 DI(Dependency Inversion) 즉, 의존성 역전을 하면, 의존성 방향과 제어의 흐름을 반대로 바꿔줄 수 있습니다.
예를 들면, Clean Architecture 에서 가장 안쪽의 Domain 영역에 Repository 인터페이스를 만들어두고, Data 영역에서 Repository 구현체를 만들게끔해서 Domain은 다른 어떤 영역에도 관심이 없도록 설계가 가능하게 하죠.
여기서 의존성은 Data 가 Domain 에 의존하는 방향이지만, 제어의 흐름은 Domain 에서 Data 로 흘러갑니다.(Upstream)

이런 의존성 방향의 정리도 좋지만,
Domain 입장에서는 Repository 의 세부구현에 관심이 없게 됩니다.
SOC(Seperation of Concern)이죠.

유형은 동시 실행 정책을 담당합니다.

번역이 잘 이해가 안가네요.

Types are responsible for their concurrency policy.

Type 은 Class 또는 Object 라고 보면 좋겠어요.
즉, 어떤 클래스가 하는 일이 Thread 관리가 필요한 일이라면,
바로 그 클래스가 자신의 Thread 전략을 잘 알고 있어야한다는 점입니다.
UI thread 에서 호출하더라도, 사용자 경험을 끊지 않도록
스스로 Thread 를 잘 선택해서 과업을 수행해야할 책임이 있어요.

참고

https://developer.android.com/topic/architecture?hl=ko

profile
아직 멀었습니다

0개의 댓글