image-20240506194240246.png

핵심

  • 소프트웨어를 고수준과 저수준으로 경계 짓고, 의존성 단방향 원칙을 따르는 아키텍처
  • 자주 변경되는 것(저)과 변경되지 않는 것(고)의 경계를 나눠 분리시키자는 것
    • 핵심: 계층 분리(layering) 를 통한 관심사 분리
    • presentation, domain, data layer로 나눔

특징

  • 소스 코드 의존성은 반드시 안쪽으로, 고수준의 정책을 향해야 한다: 의존성 단방향 원칙
  • 내부: 고수준, 추상화되어 변경이 잘 안됨
  • 외부: 저수준, 구체화되어 변경이 잘 됨
  • 외부는 내부를 의존, 내부는 외부의 존재를 모른다.
    • 내부는 외부에 영향을 주지 않음
  • 경계를 넘을 때는 추상화된 고수준의 인터페이스를 통한, 의존성 역전과 주입을 적용
    • 저수준의 구현에 의존하던 것을 인터페이스에 의존하게 변경 (저->고)
    • 소스 코드의 의존성(저→고)제어 흐름(고→저) 을 반대(역전)로 됨

구글 권장 아키텍처와 차이

  • 구글 권장 아키텍처에서 domain layer이 옵셔널

  • 구글 권장 아키텍처는 domain -> data layer를 참조함 (알고 있음)

    • domain layer가 프레임워크나 라이브러리에 종속될 수 있음
  • 서비스가 커지고 비즈니스 로직이 늘어날 수록 ViewModel이 비대해지고,

  • 반복되는 비즈니스 로직들도 생겨났다. Domain layer 를 도입하여 관심사 분리가 필요

  • domain layer는 자체가 어떠한 언어로든 프레임워크나 라이브러리에 종속되지 않아(순수 kotlin) 테스트, 모듈화가 용이

왜 쓰냐?

  • 모바일 환경에서 사용자가 다양한 앱을 시도때도 없이 바꾸기도 하고 전화나 알림 등의 작업도 동시에 하기 때문에
    • 앱에서 사용자 흐름이 중단되지 않고 연속적으로 흘러가도록 처리해야 함
  • App 컴포넌트 에 앱 데이터나 상태를 저장해서는 안되며, 앱 구성요소가 서로 종속되도록 개발해선 안됨
    • 단위 테스트 하기 매우 어려워짐
    • 생명주기에 의해, 메모리 릭이 발생 할 수도 있음
  • 우리의 경우 멀티 모듈을 도입 -> 클린 아키텍처가 멀티 모듈에는 적합하다 생각

  • 여러 모듈들을 조립하여 다른 앱 개발에 활용: 확장성 UP

  • 수정된 모듈만 빌드, 시간 단축: 생산성 UP

    • 모듈화를 통해 클린 아키텍쳐의 계층을 분리하고, 모듈들 간에 알아야 하는 대상과 몰라야 하는 대상의 제약이 강제됨: 휴먼 에러 제거

image-20240507211447507.png

  • app 모듈: app 의 진입점이다.

  • feature 모듈 ( = presentation layer)

    • 독립적인 기능을 분리하였다. (home, playlist, search, my, player 등등)
  • core 모듈

    • 다른 모듈에서 자주 사용 하는 공통 모듈이다.
    • ui ( = presentation layer) : 다양한 기능에서 공통적으로 사용하는 UI를 포함하여 UI의 일관성을 유지하는데 도움을 준다.

    • domain ( = domain layer) : 앱의 비즈니스 로직을 캡슐화 한다. domain 모듈은 안드로이드의 의존성이 없는 순수 Java/Kotlin 코드로만 구성한다.

    • data ( = data layer) : data를 CRUD 한다.

장점

  • 도메인 단위 혹은 viewmodel 의 단위 테스트가 쉽게 가능

  • 유저의 동작으로 시작해서 화면에 보여지는 뷰의 데이터들의 흐름에 대해 파악하기 쉬워짐

    • UI(View) → VM(프레젠터) → Usecase → Repository → Datasource
  • 신규 개발자들도 파일 이름이나 클래스 명으로 어떤 기능을 해야 하고, 하고 있는지 알기 쉬워짐

  • domain과 data간의 분리가 이루어져 있기 때문에, 데이터 소스를 변경해도 domain 모듈에는 영향이 없기 때문에 비즈니스 로직은 피해없이 안전

  • 모듈간의 결합도가 낮아짐 (서로 영향을 덜 줌)

단점

  • 많은 파일들이 생겨남
  • 단순 포워딩을 위한 Usecase가 생겨남
  • 과도하게 집착하면, layering을 위한 수단으로 코드를 짜게 됨 (주객전도)

구성 요소

image-20240506195142209.png

  • Entitiy : 핵심 비지니스 규칙을 캡슐화
  • Use Case : 비즈니스 로직을 정의
  • Interface Adapter : 어댑터들로 구성, Controller, Presenter, Gateway 가 속함. 인터페이스 역할
  • Framwork & Drivers : 시스템의 핵심 업무와는 관련 없는 세부 사항.

layer

image-20240506195132337.png

Presentation

  • 뷰(View): 직접적으로 플랫폼 의존적인 구현, 즉 UI 화면 표시와 사용자 입력을 담당합니다.단순하게 프레젠터가 명령하는 일만 수행합니다.
  • 프레젠터(Presenter): MVVM의 ViewModel과 같이, 사용자 입력이 왔을 때 어떤 반응을 해야 하는지에 대한 판단을 하는 영역입니다. 무엇을 그려야 할지도 알고 있는 영역입니다.

Domain

  • 유즈 케이스(Use Case): 비즈니스 로직이 들어 있는 영역입니다.

  • 모델(Entity): 앱의 실질적인 데이터가 정의

Data

  • 리포지터리(Repository): 유즈 케이스가 필요로 하는 데이터의 저장 및 수정 등의 기능을 제공하는 영역으로,

    • 데이터 소스를 인터페이스로 참조하여, 로컬 DB와 네트워크 통신을 자유롭게 할 수 있습니다.
  • 데이터 소스(Data Source): 실제 데이터의 입출력이 여기서 실행됩니다.