성장기록지

Android의 Clean Architecture란? 본문

안드로이드

Android의 Clean Architecture란?

pengcon 2025. 1. 7. 14:21

Clean Architecture

Robert C. Martin (Uncle Bob)가 만든

흔히 과녁모양으로 불리는 그림을 토대로 구성한 아키텍쳐를 의미한다.

복잡한 소프트웨어 시스템을 보다 관리 가능하고 유지보수 가능한 형태로 구축하기 위한 지침을 제공한다.

Clean Architecture의 모든것이 아래에 담겨있다고 볼 수 있다.

 

Clean Architecture의 이점

The Clean Code Blog에 의하면, Clean Architecture가 시스템에 주는 이점은 아래와 같다고 한다.

영어로 읽기 쉽지 않으므로 하나씩 해석해보도록 하겠다.

  1. Independent of Frameworks. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
  2. Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
  3. Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
  4. Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
  5. Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.

1. Clean Architecture는 프레임 워크에 독립적이다.

  • Clean Architecture는 일부 기능이 포함된 라이브러리 (곧 프레임워크)에 의존하지 않는다.
  • 이를 통해 프레임워크의 제약에 시스템을 맞추는 것이 아니라, 시스템의 도구로써 프레임워크를 활용할 수 있게 한다.
  • 특정 프레임워크(예: Android, Spring, Django 등)에 의존하지 않으므로 프레임워크가 변경되더라도 핵심 로직은 영향을 받지 않는다고 이해하였다.

2. Clean Architecture는 테스트를 용이하게 해준다.

  • The business rules(Entity)를 테스트하는데에 외부 요소를 필요로 하지 않는다.
  • 외부요소는 데이터베이스, 네트워크 등을 말한다.

3. Clean Architecture는 UI에 독립적이다.

다른 시스템 변경 없이, UI를 쉽게 변경할 수 있다. 예들 들면, 웹 UI에서 Console UI로 변경한다 할때, The business rules(Entity)를 변경없이 그대로 사용할 수 있다.

 

4. Clean Architecture는 DB와 독립적이다.
The business rules(Entity)이 DB에 바인딩 되지 않으므로, DB의 종류를 쉽게 변경할 수 있다.
예를 들면, Oracle에서 SQL Server, for Mongo, BigTable, CouchDB 등등으로 쉽게 변경 가능하다.

 

5. Clean Architecture는 외부와 독립적이다.
The business rules(Entity)는 외부에 대해 알필요가 없고, 전혀 알지 못한다.
이 덕분에 1-4의 이점을 가져올 수 있다.


Dependency Rule (종속성 규칙)

위 그림에서 의존성 법칙은 Entites로 향하는 화살표를 의미한다.

원의 안쪽으로만 의존성이 존재해야 한다는 뜻이다.

쉽게 말하면, 바깥 쪽의 요소 A는 안쪽의 요소 B를  필요로 한다는 의미로, A --> B로 표현할 수 있다.

이에 따라 클린 아키텍쳐 그림을 해석하자면,  항상 원의 안쪽 방향으로만 의존성이 존재해야하고, 바깥쪽 방향으로의 의존성은 존재하지 않아야한다는 의미로 해석할 수 있다.

 

의존의 방향은 변경의 유연성과도 관련이 있다.

의존의 방향이 안쪽으로만 향하기 때문에, 바깥쪽에 있을수록 변하기 쉬운,

안쪽에 있을수록 변하기 어려운 요소라 이해할 수 있다.

 

하지만 안쪽의 요소가 바깥쪽 요소를 항상 필요로 하지 않을까 ?

그렇지 않다. 다만 안쪽의 요소가 의존관계를 회피하여 바깥쪽 요소를 사용한다.

이는 의존성 역전 법칙과 관련이 있다. (아래 서술)


Clean Architecture의 Layer

Clean Architecture의 각 Layer들을 설명하기 위해 상단의 과녁 그림을 90도 회전시켜 보겠다.

 

이전에 다뤘던 안드로이드 권장 아키텍쳐와 유사하게 구성되어 있다.

각 계층이 의미는 다음과 같다.

 

프리젠테이션 계층(Presentation Layer)

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

도메인 계층(Domain Layer)

  • 유즈 케이스(Use Case): 비즈니스 로직이 들어 있는 영역이다.
  • 모델(Entity): 앱의 실질적인 데이터이다. 해당 소프트웨어의 중심이 된다.
  • Repository Interfaces : 도메인 계층에서 데이터 소스의 구현에 의존하지 않고 데이터를 요청하거나 저장할 수 있도록 한다. (데이터가 어디서 오는지 몰라도 데이터를 사용할 수 있어야 한다.)
  • Use cases는 data와 1개 이상의 Repository Interfaces를 결합한다.
  • 도메인 레이어는 의존성이 모이고, 핵심 비즈니스 규칙을 포함하는 중요한 레이어이므로 다른 레이어들과는 달리 잘 바뀌면 안된다.

Domain Layer는 가장 안쪽의 레이어이다. 앞서 언급한 의존성 법칙에 의해, Domain Layer는 다른 레이어를 대상으로 의존성을 가지지 않는다.

어떻게 Domain Layer는 의존성을 가지지 않을 수 있을까?
이는 SOLID 원칙 중 의존성 역전 법칙에 해당하는 interface를 사용한 추상화 덕분이다.

Domain Layer는 Repository를 추상화시켜 사용하고 있기 때문에, 위와 같은 의존이 생겨나지 않게 된다.
즉, Domain Layer는 Data Layer에서 구현될 Repository Interfaces를 사용하면서, 의존을 회피하게 된다.
추상화가 없었다면, Domain Layer의 Use cases가 Data Layer의 Repository를 사용해야 한다.

이것이 바로 Repository Interfaces가 Domain Layer에 포함되는 이유이자,
Repository Implementations가 Data Layer에 포함되는 이유라고 볼 수 있다.
의존성 역전이란?
객체 지향 프로그래밍에서 의존 관계 역전 원칙은 소프트웨어 모듈들을 분리하는 특정 형식을 지칭한다. 이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.
그냥 쉽게 말하면, 인터페이스로 만들고, 도메인 계층에서 인터페이스를 참조하면 된다.

 

데이터 계층 (Data Layer)

  • 리포지토리(Repository): 유즈 케이스가 필요로 하는 데이터의 저장 및 수정 등의 기능을 제공하는 영역으로, 데이터 소스를 인터페이스로 참조하여, 로컬 DB와 네트워크 통신을 자유롭게 할 수 있다.
  • 데이터 소스(Data Source): 실제 데이터의 입출력이 여기서 실행된다.
  • Data Layer는 Domain Layer를 대상으로 의존성을 가진다.

Repository Implementations는 1개 이상의 Data Sources를 포함한다.

Data Layer가 가진 책임 중 하나로, Domain Layer가 사용하는 Repository Interfaces에 대한 구현을 할 수 있다.

왜냐면 Domain Layer는 Data Layer가 구현해줄거라 생각하고 Repository Interfaces를 사용했기 때문이다.

 

Repository는 다른 Data Source들을 결합/조정한다.

Repository 여러 Data Source들을 결합하는 경우로, Local Data Source과 Remote Data Source의 결합에 대해 이야기할 수 있다. 아래는 직접 생각해본 2가지 예시이다.

  • 사용자 데이터를 로컬(Local) 캐시(Room, SharedPreferences 등)에 저장하면서, 동시에 원격(Remote) 서버에서 최신 데이터를 가져와야 하는 경우.
  • 인터넷 연결 여부에 따라 데이터를 로컬에서 가져오거나, 서버에서 동기화하는 로직이 있어야 하는 경우.

 

결론적으로 리포지토리 패턴이란??

데이터 출처 (data source)와 관계 없이, 동일한 인터페이스로 데이터를 사용할 수 있게 하는 패턴을 의미한다.

위의 예시처럼 Room(내부저장소)으로 관리되는 데이터와 (local data source data) , Retrofit2를 통해 받아오는 데이터(remote data source data)의 구분을 없애, 해당 데이터를 사용하는 Domain Layer가 데이터 출처(data source)를 알 필요 없게 해준다.

 

dataSource와 dataSourceImpl

Data Layer의 Data Source도, 위에서 봤던 의존성 역전 법칙의 적용으로,

추상화 되어 interface와 Implementations으로 구성된다.
즉, Repository - - -> Data Source의 의존에 대한 회피이다.

이렇게 의존을 없애면, Data Source의 변경시, Repository에 대한 영향을 줄일 수 있다.


Clean Architecture의 Data Flow

사용자의 인터렉션이 발생하면 이벤트는 위에서 아래로, 아래서 위로 흐른다.

사용자가 버튼을 클릭하면 위의 과녁그림에서

UI  프레젠터(ViewModel)  유즈 케이스  엔티티  리포지터리  데이터 소스로 이동하게 된다.

의존성 역전과 관련이 있으므로, 아래 그림을 보며 추가적으로 설명을 하겠다.

 

그림에서 데이터 계층의 엔티티는 과녁 모양 그림의 엔티티가 아니다. 원의 엔티티는 도메인 계층의 모델이며, 데이터 계층의 엔티티는 네트워크나 로컬 DB에서 받아온 DTO를 의미한다.

 

따라서 계층을 횡단할 때 해당 계층에 맞게 변환해야 한다. 도메인 계층에서 모델이 트랜스레이터를 거쳐, 데이터 계층의 엔티티로 변환되는 것이고, 이는 반대로도 가능하다.

결론적으로 트랜스레이터를 통해 toDomain()과 toDTO()를 진행한다고 보면 된다.

 

또한 실제로 도메인 계층은 데이터 계층을 참고하고 있지 않는다. 아까 서술한 의존성 역전 법칙 덕분이다.

 

클린 아키텍처가 필요한 이유

위와 같이 클린 아키텍쳐를 학습하였을 때, 결론적으로 클린아키텍쳐가 왜 필요한지 생각해보자.

도메인 레이어는 상술했듯이 비즈니스 로직이 모여있는 레이어이다.

그런데 도메인 레이어에 의존성이 있어 애플리케이션의 변경사항이 있을때마다 도메인 레이어를 수정한다면

비효율적이라고 생각이 될 것이다.

클린아키텍쳐는 이러한 점을 고려해 각 계층이 독립적으로 설계되어 있으므로, 최소화된 변경사항 및 유연한 확장구조를 갖게 되는 강점이 있다고 요약할 수 있다.  

 

다음글은 진행한 프로젝트에서 왜 클린 아키텍쳐를 적용하였고, 어떻게 적용하였는지 서술하겠다.

참고 자료

https://meetup.nhncloud.com/posts/345

 

[Android] 요즘 핫한 Clean Architecture 왜 쓰는 거야? : NHN Cloud Meetup

[Android] 요즘 핫한 Clean Architecture 왜 쓰는 거야?

meetup.nhncloud.com

 

 

https://velog.io/@sery270/Android%EC%9D%98-Clean-Architecture%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-n9ihbaj4

 

🏛 Android의 Clean Architecture에 대해 알아보자 !

오늘은 제가 Android 개발자로 활동하는 MARU와 관련된 주제를 가지고 왔습니다!

velog.io

 

 

https://proandroiddev.com/clean-architecture-data-flow-dependency-rule-615ffdd79e29

 

Clean Architecture Guide (with tested examples): Data Flow != Dependency Rule

Hello everyone! 👋 In this story I want to explain Clean Architecture (with tested examples) & talk about the most common mistake when…

proandroiddev.com

 

https://medium.com/cj-onstyle/android-%EB%B2%84%ED%8B%B0%EC%BB%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%9D%98-%ED%81%B4%EB%A6%B0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%8F%84%EC%9E%85-a26d833e103

 

왜 Android 신규 프로젝트는 클린 아키텍처를 도입하였는가

소프트웨어 개발은 복잡한 문제를 해결하기 위해 코드를 작성하는 것 이상을 필요로 합니다. 단순히 결과론으로 화면을 보여주는 것만 생각하고 개발한다면, 코드는 점차 커지며 나중에는 손볼

medium.com