본문 바로가기
Android/Architecture

안드로이드 Clean Architecture - 개념

by 태크민 2023. 5. 27.

클린 아키텍처의 등장

특정 수준 혹은 복잡도를 가진 애플리케이션을 위한 고품질 코드를 작성하려면 상당한 노력과 경험이 필요하다. 또한, 애플리케이션은 고객의 요구 사항을 충족 할 뿐만 아니라 유연하고 테스트 가능하며 유지 관리가 가능해야 한다.

이러한 문제에 대한 해결책으로 Robert C. Martin은 2012년에 Clean Architecture 개념을 제시 하였다.

 

 

클린 아키텍처의 개념

클린 아키텍처는 계층을 크게 나누어서 관심사를 분리, 각 분리된 클래스가 한가지 역할만 할 수 있도록 구현하는 방식이다.

 

모든 의존성 규칙은 반드시 외부에서 내부로 향해야 한다.

클린 아키텍처는 계층 구조에서 외부에서 내부로 의존성을 가지고 있기 때문에 내부로 갈 수록 의존성은 낮아지는 특징을 가진다. (위 그림에서는 원 안쪽으로 갈 수록 의존성이 낮아지는 것을 볼 수 있다.)

 

예를들어 위의 계층 이미지에서 가장 바깥의 DB와 가장 내부의 Entity를 보자.

DB의 기준으로 Entity가 변화(내부 계층이 변화) 하게 되면 DB 자체에서 저장할 데이터 타입이 변경될 가능성이 있는 등 내부의 변화로 동작을 행하는 계층에 영향을 미칠 수가 있게 된다. 하지만 Entity는 실제로 사용할 데이터 클래스이기 때문에 DB가 변경된다고 하더라도 Entity에는 아무런 영향이 없어야 하는 것이다.

반대로, Entity는 가장 내부에 있는 계층이기 때문에 다른 어떤 계층의 변화에도 영향을 받지 않으며, 오로지 자신의 변화만이 다른 계층에 영향을 끼칠 수 있게 된다.

이것이 DB(바깥 계층)가 의존성이 높고, Entity(내부 계층)이 의존성이 낮다는 의미이다.

 

 

클린아키텍처의 이점

  • 쉽게 패키지 구조 탐색 가능
  • 프로젝트의 유지 보수가 편리해진다.
  • 새로운 기능을 추가 할 때 안정적으로 빠르게 적용이 가능하다.

 

 

안드로이드에서의 클린 아키텍처 구조

안드로이드에서의 클린아키텍처 구조는 Presentation, Domain, Data 총 3개의 계층으로 크게 나눠지 된다.

Presentation(UI) -> Domain <- Data 방향으로 의존성이 있다.

 

Presentation 계층:  Domain 계층에 의존성을 가지고 있는 계층, 화면과 입력에 대한 처리 등 UI와 직접적으로 관련된 부분을 담당한다.

  • UI(Activity, Fragment)
  • VM(각 화면에 사용될 ViewModel)
  • DI

Data 계층: Domain 계층에 의존성을 가지고 있는 계층, 말 그대로 Data 들을 CRUD하는 계층이라고 생각하면 편하다.

  • 서버나 DB 를 연결하는 역할을 하는 DataSource Interface와 구현부
  • API 통신과 그 결과로 가져오는 Data Entity. 내부 DB (Room)과 DAO.
  • 위의 데이터(서버, 로컬)를 사용하기 위한 Repository 구현부.
  • Data 계층 데이터(받아오는 전체 데이터 형태)와 Domain 계층 데이터(실제로 사용하는 데이터 형태)로 변환해주는 Mapper 클래스

Domain 계층: 의존성을 가지고 있지 않은 계층. 비즈니스 로직에 필요한 Data Model과 UseCase가 포함되어 있는 계층이다. (Domain 계층은 독립적이다.)

  • Usecase
  • Reopository Interface

아래 사진은 구글에서 추천하는 Repository 패턴이다. UseCase 클래스의 매개변수는 Repository Interface 인 것이고, Data 계층의 Repository 구현체 클래스에서 Repository Interface 를 상속하고 있다. 당연히 Domain 계층은 독립적이고, Data 계층은 Domain 계층에 의존하고 있는 것이다.

 

프로젝트 구조에 따라 계층을 나눠봤다.

Presentation Layer에는 화면의 표시, 애니메이션, 사용자 입력 처리 등 UI에 관련된 모든 처리를 갖는다.

Domain Layer에는 앱의 실질적인 데이터가 여기에 구현된다.

Data Layer에는 실제 데이터의 입출력이 여기서 실행된다.

 

각 계층별 의존성

Domain 계층은 의존성이 없다. 즉, 자기가 바뀌면 영향을 줄 뿐 다른 계층의 변화에 영향을 받지 않는다.

 

Data 계층은 Domain 계층의 변화에 영향을 받는다. 즉, Domain 계층의 무언가(클래스)를 가져와서 사용한다.

(Mapper클래스, Repository 구현부 구현을 위해 Domain 계층 참조)

 

Presentation 계층은 Domain계층의 변화에 영향을 받는다. Domain 계층에서 선언된 UseCase는 presentation계층의 ViewModel에서 직접사용하기 때문에 영향을 끼치게 된다.

 

QUIZ

UseCase가 꼭 필요할까? 비즈니스 로직을 Usecase로 분리함으로써 얻은 이점은 무엇일까?

1. ViewModel의 역할을 명확하게 분리할 수 있다.

  • ViewModel에서 UseCase를 호출하는 방식으로 구현하면, 해당 ViewModel이 어떤 역할을 수행하는지 직관적으로 파악할 수 있다.
  • 유지보수뿐만 아니라, 협업 시에도 코드의 가독성과 이해도가 높아진다.

2. 의존성을 줄이고 변경에 유연하게 대응할 수 있다.

  • ViewModel이 직접 Repository를 사용하면, Repository의 변경 사항이 ViewModel에도 직접적인 영향을 미친다.
    따라서, Repository가 수정되면 이를 사용하고 있는 여러 ViewModel에서 수정이 이루어져야한다.
  • 하지만, UseCase 를 사용하게 되면 영향이 있는 UseCase 를 사용하는 부분에서만 수정을 하면 되기 때문에 의존성이 줄어든다.

3. ViewModel에 로직이 집중되는 것을 방지할 수 있다.

  • UseCase 없이 ViewModel에서 비즈니스 로직을 처리하면, ViewModel이 방대해지고 복잡해질 수 있다.

4. 비즈니스 로직의 재사용성을 높일 수 있다.

  • 동일한 비즈니스 로직이 여러 ViewModel에서 필요할 경우, UseCase를 활용하면 중복을 방지할 수 있다.

Repository, UseCase에는 각각 어떤 로직 로직이 들어가면 좋을까?

✔ 네트워크 관련 로직"은 DataSource에서 수행하고

Repository는 DataSource에서 받은 raw한 데이터를 도메인 모델로 변환하여 여러 UseCase에서 활용할 수 있도록 제공해야 한다.
UseCase에서는 메시지 필터링 등 비즈니스 로직을 적용해야 한다.

 

만약 Repository에서 도메인 모델 + 비즈니스 로직(필터링)을 적용하면 유지보수가 어려워지고, 중복 코드가 발생한다.

필터링 로직이 특정 Repository에 포함되면, 다른 UseCase에서 같은 필터링을 원할 때 재사용이 어렵다. 결국, 동일한 로직을 여러 Repository에서 중복해서 구현해야 하는 문제가 생길 수 있다.

 

클린아키텍처의 의존성 역전에 대해 설명

의존성 역전 원칙(DIP)은 고수준 모듈이 저수준 모듈에 직접 의존하지 않고, 인터페이스(추상화)에 의존하도록 설계하는 원칙이다. 이를 클린 아키텍처에 적용하면 Domain계층이 Data계층에 직접 의존하지 않아 변경에 유연하고 유지보수성이 향상된다.

예를 들어, ViewModel → UseCase → Repository(인터페이스) ← Repository(구현체) 구조를 유지하면, Repository의 구현(API, DB 등)이 변경되더라도 UseCase와 ViewModel은 영향을 받지 않는다.

이를 통해 확장성과 테스트 용이성이 증가하며, 유지보수 시 수정 범위를 최소화할 수 있다.

 

클린아키텍처를 사용할때 멀티 모듈을 자주 사용하는데, 멀티 모듈의 장단점은?

장점

1. 의존성 규칙 강제

  • 단일 모듈에서는 실수로 의존성 규칙을 위반하기 쉽지만, 멀티 모듈에서는 build.gradle에서 명시적으로 의존성을 추가해야만 다른 모듈을 사용할 수 있어 의존성 규칙을 강제할 수 있다.

2. 빌드 시간 단축

  • 멀티 모듈을 사용하면 변경된 모듈만 빌드하므로 전체 빌드 시간이 감소할 수 있다.
  • 하지만, 모듈 간 의존성이 복잡해지거나, 종속성이 많아질 경우 빌드 시간이 증가할 수도 있다.

3. 모듈 단위 테스트 가능

  • 특정 기능이나 도메인 로직을 개별 모듈로 분리하면 독립적인 단위 테스트가 가능해진다.

4. 코드 재사용성 증가

  • 레이어별, 기능별로 모듈을 나눠서 작성하게 되면 해당 기능이 필요할 때 해당 모듈에 대한 의존성을 추가해서 사용하면 되기 때문에 재사용성이 높아진다.

단점

Gralde 설정을 개별적으로 추가 설정 해줘야하고, 만약 멀티모듈에서 공통적으로 사용하는 특정 라이브러리의 버전이 바뀌었다면 모듈을 모두 방문해서 버전을 올려줘야한다.

 

 

 

출처

[Android] Clean Architecture 실전 압축 정리 - 개념 (tistory.com)

 

[Android] Clean Architecture 실전 압축 정리 - 개념

처음 학습하면서 작성한 글입니다. 필요시 추후 내용을 수정할 예정입니다. 틀린 부분이 있으면 언제든 지적해주면 감사하겠습니다 :) 클린 아키텍처를 공부하다 보면 모든 블로그에서 다음과

heegs.tistory.com

[안드로이드] 클린 아키텍처(Clean Architecture) 정리 및 구현 (tistory.com)

 

[안드로이드] 클린 아키텍처(Clean Architecture) 정리 및 구현

[2021-04-28 업데이트] [2022-02-01 업데이트] Hilt 사용한 프로젝트 링크 하단에 추가 [프로젝트] github.com/mtjin/mtjin-android-clean-architecture-movieapp mtjin/mtjin-android-clean-architecture-movieapp Clean Architecture 학습 및

youngest-programming.tistory.com

https://velog.io/@galaxy/Clean-Architecture

 

Clean Architecture

제 머릿속에 이해된 Android Clean Architecture 에 대해 정리한 내용입니다.

velog.io

https://class-programming.tistory.com/144

 

MVVM + Clean Architecture를 활용한 영화검색 앱

이 프로젝트는 약 1년전 쯤 했던 프로젝트였다. 그 때는 클린아키텍처는 적용하지 않았다. 이번에는 갓수아님 소스코드를 참고해 클린아키텍처까지 적용해봤다. 스플레시, 로그인, 검색화면 총

class-programming.tistory.com