오늘의 주제는 로버튼 마틴 형님의 "클린 아키텍처"라는 개념이다.
많은 기업들이 해당 아키텍처 구조를 사용하고 있으며, 비즈니스 로직 덩어리가 클수록 장점이 부각되는 구조이다.
하지만 기존의 "클린 아키텍처"라는 개념은 분야에 구애받지 않는 개념이라 안드로이드에서는 완벽하게 호환되지 않는다.
그래서 오늘은 안드로이드에서의 클린 아키텍처에 대해 설명하고자 한다. 구조도를 보면 컴포넌트나 의존성 구조가 조금 다르니 그 부분을 유의해서 보면 이해가 쉬울 것이다.
클린 아키텍처의 핵심적인 역할을 하는 SOLID에 대해 궁금하다면 이 포스팅을 참고하면 도움이 될 것이다.
🚌 클린 아키텍처
클린 아키텍처의 목적은 크게 네 가지이다.
- 의존성 분리
- 확장성
- 유지보수성
- 테스트 용이성
우리는 체계적인 계층 분리를 통해 관심사를 분리함으로써 위 목적들을 충족시킬 수 있는 아키텍처를 만들도록 해야한다.
로버트 마틴은 "아키텍처는 선을 긋는 기술이다"라고 할 정도로, 계층 분리를 잘 하는 것이 클린 아키텍처의 핵심이다.
위 그림은 일반적인 클린 아키텍처의 구조이다.
계층을 뛰어넘거나 양방향 의존성을 가지지 않으며 오로지 외부에서 내부로 의존성을 가진다.
안드로이드에서의 클린 아키텍처도 기본 개념 자체는 위와 동일하지만 의존성 구조가 조금 다르다고 생각하면 이해가 쉽다.
위 그림이 안드로이드 클린 아키텍처 구조이다.
기존의 외부에서 내부로 의존성을 가지는 구조가 아니라 data, presenation 계층이 domain 계층에 대한 의존성만 가진다는 점이 가장 큰 차이점이다.
클린 아키텍처는 내부의 "정책"과 외부의 "메커니즘"으로 이루어져 있는데,
여기서는 Domain 계층이 "정책", Data 계층과 Presentation 계층이 "메커니즘"이다.
외부의 변경(Data, Presentation, Framework)이 정책(Domain)에 영향을 주지 않기 때문에 비즈니스 로직을 완벽하게 캡슐화하여 변경의 전파를 막을 수 있다.
실제 프로젝트에 적용시에는 단순 패키지 분리가 아닌 멀티 모듈을 적용하여 의존성 분리를 완벽하게 시켜야 한다.
그리고 위 그림 상에서는 translator(mapper) 클래스가 Domain 계층에 있다고 나와 있는데, 실제로 Mapper는 각 계층에 존재하지만, Data 계층과 Domain 계층 간의 매핑은 두 계층에 대한 의존성을 모두 가지고 있는 Data 계층에 위치하는 것이 맞다.
1. Domain
비즈니스 로직들의 집합이다 == "정책"들의 모임이다.
Domain 계층은 다른 계층에 의존성을 가지지 않으며, 프레임워크에 대한 의존성도 모두 제거하여 테스트에 용이한 구조로 구현해야 한다.
Domain 계층에는 다음과 같은 컴포넌트들이 포함된다.
- Model
- Domain 계층의 데이터 클래스
- Data 계층의 데이터 클래스를 Mapper를 통해 Model 클래스로 변환한다.
- 사용자가 실제 서비스를 이용하는데에 사용되는 데이터 클래스이다.
- UseCase
- Domain 계층의 핵심
- 시스템이 제공하는 기능이나 사용자의 요구사항
- ex) 사용자 - 회원가입, 로그인, 회원정보 수정, 회원 탈퇴 등
- UseCase만 보고 소프트웨어가 어떤 서비스를 제공하는지 한눈에 알 수 있어야 한다.
- Repository
- 정확하게는 Repository 인터페이스이며, Data 계층에 구현체가 존재한다.
- 이로 인해서 Domain 계층에서 Data 관련 클래스들(DataSource, Mapper, Dao, Api 등)을 사용하기 위해 의존성을 추가하지 않아도 된다.
2. Data
Data 계층은 Domain 계층에 의존성을 가지며, Local/Remote 데이터의 입출력, 매핑, 파싱과 같은 작업을 수행하는 계층이다.
데이터 클래스는 Local의 Entity 클래스, Remote의 Dto 클래스가 있다.
Data 계층에는 다음과 같은 컴포넌트들이 존재한다.
- DataSource
- 데이터베이스, 네트워크 등의 외부 리소스에 접근해서 데이터 관련 작업을 수행한다.
- RepositoryImpl 계층에서 DataSource와 Mapper를 사용하여 데이터를 매핑하고 관련 로직을 구현한다.
- RepositoryImpl
- Domain 계층의 Repository 인터페이스의 구현체(DIP)
- 실질적인 데이터 관련 작업을 수행하는 메서드들을 포함한다.
- Mapper
- 로컬-리모트간 데이터 매핑과 계층간 데이터 매핑을 수행하는 클래스이다.
- 다른 포스팅들에는 Translator(Mapper) 클래스가 Domain 계층에 위치한다고 되어 있는데, 그렇게 되면 Domain 계층은 Data 계층을 모르기 때문에 데이터 매핑이 불가능하다.
- Local
- Dao, Database(Room), Entity와 같은 Local 데이터를 위한 클래스들이 존재한다.
- Remote
- Api, Dto와 같이 네트워크 통신(Remote)을 위한 클래스들이 존재한다.
3. Presentation
Presentation 계층은 Domain 계층에 의존성을 가지며, View와 관련된 로직을 수행하는 계층이다.
Presentation 계층에는 다음과 같은 컴포넌트들이 있다.
- View
- View, Activity, Fragment 등등
- ViewModel(Presenter)
- 사용자가 View와 상호작용을 통해 요청하는 작업을 Domain 계층의 UseCase 클래스를 참조하여 수행한다.
- 이외 View 관련 클래스들
사용하는 아키텍처 패턴에 따라서 ViewModel은 Presenter로도 대체될 수 있다.
우아한스터디를 클린아키텍처 주제로 지원했는데 아쉽게 탈락했다. 뭔가 내가 얻을 수 있는 것만 적고 그 사람들이 날 왜 뽑아야하는지에 대해서는 자세히 적지 않아서 그런 것 같다. 겨울 시즌에 열린다면 그 때는 꼭 붙어어지
2편은 클린 아키텍처에서 중요한 개념인 의존성 역전 원칙(DIP)에 대해 포스팅할 예정이다.
'개발 > Android' 카테고리의 다른 글
[안드로이드] 클린 아키텍처 - (3) 멀티 모듈 패키지 구조 (0) | 2023.05.23 |
---|---|
[안드로이드] 클린 아키텍처 - (2) 의존성 역전 (0) | 2023.05.16 |
[안드로이드] 오픈소스 라이선스 고지 (0) | 2023.05.10 |
[안드로이드] ViewModel에서 context를 사용하는 방법 (1) | 2023.05.10 |
[안드로이드] AAC ViewModel과 MVVM ViewModel (0) | 2023.03.26 |