Android 앱을 Clean Architecture 로 구성해야 할까?
안녕하세요. GDG Incheon Organizer 이준범입니다. 😄
오늘은 Android 앱을 Clean Architecture로 구성해야 할까? 라는 주제로 얘기해 보고자 합니다.
Android 앱을 만든다고 생각해보겠습니다.
어떤 Architecture로 앱을 구성할까요?
가장 쉽고 빠르게 접근할 수 있는 방법은 Android Developer 사이트에 명시된 권장 Architecture를 선택하는 방법입니다.
대부분 보셨을 거라 생각하기에 간단하게 짚고 넘어가겠습니다.
UI Layer
데이터를 화면에 표시하는 역할과 사용자와의 상호작용을 담당합니다.
Domain Layer
선택사항으로 표시된 Domain Layer를 추가함으로써 UI Layer와 Data Layer 간의 상호 작용을 단순화하고 재활용하기 좋게 만들 수 있습니다.
Data Layer
앱에 필요한 데이터를 저장, 불러오는 역할을 합니다.
Android 권장 Architecture는 Layered Architecture (Multitier Architecture라고도 불림)와 유사합니다.
이 그림은 3-tier로 구성된 Layered Architecture 입니다.
다시 돌아가서 권장 Architecture를 토대로 얘기해보겠습니다.
아래 이미지는 Data Layer의 상세 모습입니다.
여기서 Data Layer를 말하는 이유는 다음과 같습니다.
- 3개의 Layer 중 가장 깊은 Layer입니다.
- 데이터를 관리하여 UI, Domain Layer에 필요한 데이터를 전달하는 핵심 역할을 담당합니다.
즉, 데이터 중심으로 보여주는 앱이라면 이 Architecture가 잘 맞을 수 있습니다.
현재 개봉한 영화 목록을 보여주고 영화에 대한 점수와 후기를 기록할 수 있는 앱을 만든다고 생각해보겠습니다.
MovieActivty에서는 페이지가 시작되면 MovieService에 영화 정보를 요청하고 실제 데이터는 MovieRepository에 요청해서 화면에 보여주게 됩니다.
만약 리뷰 작성 기능이 생기고 리뷰도 보여줄 수 있게 되면 어떻게 변화할까요?
마찬가지로, 보고 있는 영화 정보에 점수와 후기를 기록한다면 MovieActivity에서 발생한 액션으로 ReviewService에 작성한 점수와 후기를 전달하고 ReviewRepository를 통해 데이터로 저장하게 됩니다.
어떻게 만들겠다 생각하셨나요?
이런 데이터를 받아야 하고 이 데이터 주고 받는 Repository부터 생각하지 않으셨나요?
네 저도 그렇게 생각했습니다. Data Layer가 핵심이므로 데이터의 상태를 중심으로 생각해서 Repository부터 생각하게 됩니다.
즉, 어떤 데이터를 저장하고 보여줘야 하는지 상태 중심으로 생각하게 됩니다.
이 Architecture도 단점이 있습니다.
- 우선 상태 중심으로 생각하게 되지만 실제 앱의 중심은 행동입니다. 행동이 상태를 변경하기 때문입니다.
- 서비스가 점차 커지면서 Data Layer에서 바로 데이터를 처리하기 쉽게 유틸, 처리기 등이 포함되며 Data Layer가 거대해집니다.
- 거대해지는 것은 괜찮지만, Layer간의 책임을 제한하기 어렵고, 책임을 분리하기에도 어려우므로 Layer간의 책임이 섞이기 쉽고, 이는 테스트마저 어려운 길로 빠질 수 있습니다.
마지막으로 앱을 데이터를 중심으로 파악해야 하므로 코드만 보고는 핵심 정책이 무엇인지, 사용자의 유스케이스는 어떤지 파악하기 어렵습니다.
권장하는 Architecture 말고 현재 많이 보이는 Architecture는 어떤 것이 있을까요?
Architecture는 한번 정하면 변경하기 어렵기에 내가 제공하려는 서비스를 잘 전달할 수 있는 Architecture를 조금 더 알아봅시다.
구글에 Android Architecture를 검색해보면 Clean Architecture 용어가 첫 페이지에 노출되고 심지어 연관 검색어로도 나옵니다. 그리고 많은 발표에서도 Clean Architecture 주제가 종종 보입니다. 그만큼 많은 관심이 있는 주제 인 것 같습니다.
그러면 Clean Architecture를 알아보겠습니다.
Clean Architecture 구성도입니다. 행동인 유스케이스와 행동으로 변화하는 도메인 엔티티가 중심에 있습니다.
Android 권장 Architecture와 다르게 입력과 출력이 모두 가장 원의 밖에 있습니다.
각 Layer 의 역할은 같지만 의존성 역전 (DI) 로 Data Layer가 Domain Layer에 의존하게 됐습니다.
이해를 돕기 위해 Clean Architecture 구성을 더 개발스럽게 보겠습니다.
이 그림은 Hexagonal Architecture이며 Ports & Adapters Architecture로도 불립니다.
Core는 핵심 도메인이고 Adapter는 입·출력을 담당하고 있는 그림입니다.
영화 정보를 보여주던 앱은 어떻게 바뀌었을까요?
MovieActivity에서 영화 보여줘야 한다면 MovieService에 영화 정보를 요청하고 데이터는 도메인이 원하는 행동을 구현한 RepositoryImpl을 통해 받게 됩니다.
이렇게 하게 됨으로써 행동 중심의 사고가 가능하고, 가장 변경이 적은 Domain Layer만으로 UI Layer와 Data Layer를 요구사항에 맞게 바꾸기 수월해집니다.
핵심은 도메인은 Data Layer와 UI Layer를 모른다는 점입니다. 비즈니스 정책에 따라 도메인이 해야 할 행동을 정의하고 그에 따라 필요한 입·출력은 외부에 전달하는 거죠. 이 이유가 Ports & Adapters Architecture라고 부르는 이유입니다.
또한 가장 중요하고 변경이 적은 도메인에 대한 단위 테스트가 무척 쉬워집니다.
마지막으로 도메인이 자체 Entity를 정의하므로 내부 핵심 요소가 UI, Data Layer에 의해 오염되는 일이 적습니다.
하지만 이 Architecture도 단점이 있습니다.
- 도메인이 중요하지 않다면 적용하기 어렵습니다. (적용할 이유가 없죠.)
- 각 Layer가 Entity를 가지는 등 다양한 이유로 코드가 증가합니다.
첫 앱의 출시를 최대한 빠르게 개발해서 배포해야 하는데 오래 걸릴 것 같습니다.
“Android 앱을 Clean Architecture로 구성해야 할까요?”
좋을수도 있고 아닐 수도 있다? 라고 답변해 봅니다.
어떤 것이든 장단점이 있으니까요!
그럼, 어떤 앱이든 적용 가능한 완벽한 Architecture는 없을까요?
No Silver Bullet
모든 앱에 어울리는 완벽한 마법 같은 Architecture Pattern은 없습니다.
서비스의 성격과 환경, 주변 요소 (개발 시간, 팀이 어떤 목표로 달리는지) 등 다양한 요소를 판단하여 정하면 좋을 것 같습니다.
그리고,
빨리 가는 유일한 방법은 제대로 가는 것이다.
상황에 맞게 정한 Architecture는 정한 규칙대로 제대로 간다면 빠르게 변화하는 지속 가능한 앱을 만들 수 있다고 생각합니다.
그래도 안된다고요?
그럼 그때 바꾸면 돼요! 😉
끝까지 읽어주셔서 감사합니다.
모두 즐코하세요~! 🙇
[참조]
- https://en.wikipedia.org/wiki/Multitier_architecture
- https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html
- https://developer.android.com/topic/architecture
- https://namocom.tistory.com/986
- [Book] 클린 아키텍처: 소프트웨어 구조와 설계의 원칙
- [Book] 만들면서 배우는 클린 아키텍처
- [Book] 단위 테스트
- [Book] 도메인 주도 설계:소프트웨어의 복잡성을 다루는 지혜