클린아키텍처

Jini.Dev·2022년 6월 15일
0
post-thumbnail

CleanArchitecture

아키텍처란?
단어 그대로의 뜻은 건축, 설계라는 뜻입니다.
컴퓨터와 관련해 해석하자면 시스템 하드웨어 구조와, 컴퓨터 구성 요소들에 대한 전반적인 기계적 구조를 설계하는 방법이라 할 수 있습니다.

소프트웨어 아키텍처란?
소프트웨어의 구성 요소들 사이에서 유기적 관계를 표현하고 소프트웨어의 설계와 업그레이드를 통제하는 지침과 원칙이다. (위키백과)
다시 말하면 소프트웨어를 설계하는 방법이자 설계 원칙입니다.

소프트웨어 시스템의 아키텍처란 시스템을 구축했던 사람들이 만들어낸 시스템의 형태다. 그 모양은 시스템을 컴포넌트로 분할하는 방법, 분할 된 컴포넌트를 배치하는 방법, 컴포넌트가 서로 의사소통하는 방식에 따라 정해진다.
그리고 그 형태는 아키텍처 안에 담긴 소프트웨어 시스템이 쉽게 개발, 배포,운영, 유지 보수 되도록 만들어진다.

소프트웨어 아키텍처의 목표는 필요한 시스템을 만들고 유지 보수하는 데 투입되는 인력을 최소화 하는데 있습니다.
소프트웨어가 가진 본연의 목적을 추구하려면 소프트웨어는 반드시 ‘부드러워’야 합니다.

여기서 말하는 부드러운, 유연한 소프트웨어란 고객의 요구 사항에 따라 쉽게 기능을 변경하거나 추가할 수 있는 것을 뜻합니다.
기능을 쉽게 변경할 수 있도록 설계가 되어 있다면 좋은 아키텍처라고 생각됩니다.

좋은 아키텍처는 유스케이스를 그 중심에 두기 때문에, 프레임워크나 도구, 환경에 전혀 구애 받지 않고 유스케이스를 지원하는 구조를 아무런 문제 없이 기술할 수 있다.

시스템 아키텍처 관련해 육각형아키텍처(Hexagonal Architecture), DCI(Data, Context and Interaction), BCE(Boundary-Control-Entity) 등 다양한 아이디어들이 있었다.
이 아이디어들은 세부적인 차이는 있지만, 공통적인 목표는 소프트웨어를 계층으로 나눠 관심사를 분리하는 것이다.

아키텍처가 추구하는 내용들은 다음과 같은 특징을 갖는다.

  • UI, 데이터베이스, 프레임워크 등의 독립성
  • 기능 변경 및 확장의 용이성 (유지보수의 용이성)
  • 테스트 용이성

클린 아키텍처는 Robert C. Martin이 위에서 언급한 내용들을 종합적으로 포함하면서, 계층별로 관심사를 분리하고 비즈니스 로직을 캡슐화하는 소프트웨어 설계 철학이다.

각 계층 설명

  1. Entities : 엔티티는 비즈니스 규칙, 가장 일반적이면서 고수준의 규칙을 캡슐화하게 됩니다. 외부가 변경되더라도 이러한 규칙이 변경될 가능성이 적습니다.
  2. Use cases : 유스케이스는 애플리케이션에 특화된 업무 규칙을 캡슐화 하며 엔티티로부터의 데이터 흐름을 조정합니다. 유스케이스 계층의 변경이 엔티티에 영향을 줘서는 안 되며 데이터베이스, 공통 프레임워크 및 UI에 대한 변경으로부터 격리됩니다.
  3. Interface Adapters : 인터페이스 어댑터는 데이터 형식을 변환하는 역할을 하는 요소로 유스케이스와 엔티티에게 가장 편리한 형식에서 데이터베이스 및 웹에 적용할 수 있는 형식으로 변환합니다. 이 계층에는 MVP 패턴의 Presenter, MVVM 패턴의 ViewModel가 포함됩니다. 즉, 순수한 비즈니스 로직 만을 담당하는 역할을 합니다. (비즈니스 로직이란 소프트웨어 설계에 알맞게 데이터를 변경하고 가공하는 방법을 뜻한다)
  4. Frameworks & Drivers : 프레임워크와 드라이버는 상세한 정보들을 두게 됩니다. 웹 프레임워크, 데이터베이스, UI, HTTP client 등으로 구성된 가장 바깥쪽 계층입니다.

위의 아키텍처가 동작하도록 하는 가장 중요한 것은 의존성 규칙이다.
의존성 규칙은 모든 소스 코드의 의존성은 반드시 바깥쪽(저수준, 구체적인 세부사항)에서 안쪽(고수준, 정책, 추상화된 개념) 으로 향해야 한다는 것이다. 내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못하게 해야 한다.

안드로이드에서도 모듈의 변경이 다른 모듈에 영향을 미치지 않도록, 그리고 같은 모듈 내에서는 일관되고 응집력 있는 결합을 제공할 수 있도록 계층의 경계를 나눠야 하는데 다음과 같은 형태의 아키텍처를 권장하고 있습니다.

안드로이드 권장 앱 아키텍처

원래 네 개인 계층을 UI Layer (or Presentation Layer), Domain Layer, Data Layer 세개의 계층으로 분리하였습니다.

좀 더 직관적으로 표현한 그림입니다.

[출처][https://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc]

[출처][https://proandroiddev.com/clean-architecture-data-flow-dependency-rule-615ffdd79e29?gi=6d862c7bcb59]

클린아키텍처의 동심원이 꼭 4개일 필요도 없다. 그저 개념을 설명하기 위한 예시일 뿐이다. 상황에 따라 더 많은 계층을 만들고 세분화할 수 있다. 다만 계층간 의존성 규칙은 반드시 지켜야 한다. 동심원 안쪽으로 이동할수록 추상화가 높아진다.

각 레이어 설명

UI/Presentation 계층은 화면과 입력에 대한 처리 등 UI와 관련된 부분을 담당합니다. Activity, Fragment, View, Presenter 및 ViewModel을 포함합니다. UI 계층은 Domain 계층에 대한 의존성을 가지고 있습니다.

도메인 계층은 애플리케이션의 비즈니스 로직에서 필요한 UseCase가 있습니다.
UseCase는 각 개별 기능 또는 비즈니스 논리 단위입니다.
이 계층은 안드로이드를 포함해 어떠한 계층에도 의존하지 않고 java 및 kotlin 코드로만 구성하며 다른 애플리케이션에서도 사용할 수 있습니다.
UseCase외에도 Model과 Repository 인터페이스도 포함되어 있습니다.

  • Entity : 특정 영역을 표현하는 객체. ex) Pojo, DTO 등
  • UseCase : Entity와 함께 비즈니스 로직을 수행한다.
  • Repository 인터페이스 : 데이터베이스, 원격 서버와 같은 데이터 소스에 접근한다.

도메인 계층은 비즈니스 로직들을 한 계층에서 관리하는데 초점을 맞춘다. 이를 통해 코드를 깨끗하게 관리하고, 단일 책임 원칙(SRP;Single Responsibility Principle)에 부합하는 코드를 작성하기가 쉬워진다.

UI 또는 프레임워크 코드는 빈번히 변경될 수 있고, 비즈니스 로직과 관련이 없는 내용이므로 도메인 분리는 매우 중요하다. 

데이터계층은 데이터 소스(DB, 서버 등)와 상호작용을 담당하는 코드가 포함되어 있습니다. 데이터 계층은 도메인 계층에 의존성을 가지고 있습니다.

데이터 계층은 다음과 같은 두가지 책임을 갖는다.

  • 데이터 입출력 코드를 하나의 계층에서 관리한다.
  • 데이터 소스들과 데이터를 소비하는 다른 계층과의 경계를 둔다.

데이터 계층 에서는 도메인 계층에서 정의한 Repository 인터페이스를 구현한다. (Repository 패턴)
또한 mapper 클래스를 통해 데이터 계층의 모델을 도메인 계층의 모델로 변환해주는 역할도 하게 됩니다.

아무래도 UI / UX는 비즈니스 로직에 비해 상대적으로 변경할 일이 많다. 또한 UI와 관련된 유닛테스트는 어렵기 때문에 UI와 관련된 내용은 다른 코드에서 의존성이 없도록 최대한 독립적으로 만들어야 한다. UI 코드를 한 곳에서 관리함으로써 비즈니스 로직을 보호하고, 테스트도 쉽게 만든다.

사용자가 사용할 개념을 정의 할 때 어떤디비에 저장될지, 어떤 상황/뷰에 쓰일지 고민하지 않고,
사용자가 받아들이는 단위대로만 엔터티를 작성하고
작성된 엔터티를 바탕으로 어떤 행동을 할지(유즈케이스) 를 도메인레이어에 작성
그 도메인 레이어를 실제로 구현하는 것들을 데이터레이어
데이터레이어에서 가져온 값을 프레젠테이션레이어에서 보여주는 과정

도메인 레포지토리에서 정의한 인터페이스를 구현하는 건데 도메인은 데이터를 모른다. → 리턴타입이 데이터 모델일수가 없다. 엔터티에서 정의한것만이 리턴타입이 될 수 있다.
데이터레이어에서 데이터를 가져오지만, 그 결과를 엔터티로 변환을 해줘야한다.(mapper)

profile
정신 차려보니 개발자가 되어있었다.

0개의 댓글