Clean Architecture 알아보기

OlymPos 프로젝트를 시작하면서 공부해야 겠다고 마음먹은 것들이 많았는데, 그중 하나가 클린 아키텍처다.
다들 클린 아키텍처 클린 아키텍처 하니 이게 도대체 뭔진 몰라도 공부해봐야 겠다는 생각이 들었다.
기본적인 Layered Architecture(계층 아키텍처)와 Clean Architecture(클린 아키텍처)의 개념과 이 둘의 차이점을 알아볼 것이다.
또한 아키텍처를 사용하는 이유와 아키텍처 선택 기준에 대하여 생각해보고 이를 정리하고자 한다.

용어 정리

Persistence(영속성): 데이터를 생성한 프로그램이 종료되어도 데이터가 지속되는 특성. DB에 저장된 데이터는 영속성을 가진 것이고, 메모리 상에 존재하는(변수에 저장된) 데이터는 영속성을 가지지 않은 것이다.
Business Rule(비즈니스 규칙): 어떤 일이 발생했을 때 수행하는 구체적인 일(ex.주문이 들어오면 상품 수량을 하나 줄임)
Business Role(비즈니스 역할): 사용자가 버튼을 클릭하면 발생하는 어떤 일(ex.주문 접수)
Business Logic(비즈니스 로직): (비즈니스 규칙 + 비즈니스 역할) 특정 요청(ex. 상품 구매하기)에 따른 주요 로직(ex. 상품, 배송지 정보 가져오기, 결제하기 등)의 집합.
Database Driven Development(데이터베이스 주도 설계): 데이터베이스를 먼저 설계하고, 이를 토대로 패키지를 구성하고, 데이터를 조작하는데 필요한 메소드를 만드는 방식으로 개발을 수행하는 방식
Domain Driven Development(도메인 주도 설계): 비즈니스 역할과 규칙을 먼저 정의하고 이를 중심으로 설계하는 방식

Layered Architecture

단순한 구조로 이루어져 있으며 기본적인 아키텍처이다.
UI(Presentation) Layer, Business Logic(Domain) Layer, Data Access(Persistence) Layer로 분리되어 있다.

  • UI Layer - 사용자와의 상호작용을 수행하고 사용자에게 데이터를 보여준다.
  • Business Logic Layer - 어플리케이션의 모든 비즈니스 로직을 수행한다.
  • Data Access Layer - DB나 파일같은 데이터 저장소에 접근하여 필요한 데이터를 가져오는 역할이다.

각 계층의 관계는 다음과 같다.
의존성이 하위 계층(여기에선 Data Access)으로 향한다.
간단히 말하면 UI 계층은 Business Logic 계층을 알고 있고, Business Logic 계층은 Data Access 계층을 알고 있다.

장바구니에 상품을 추가하는 상황이라면,
사용자가 장바구니 담기 버튼을 누름: UI 계층에서 상호작용 인식
사용자의 장바구니 리스트에 상품을 추가함: 비즈니스 로직 계층에서 수행
사용자의 장바구니 리스트를 DB에 업데이트함: 데이터 접근 계층에서 업데이트 쿼리 실행
DB 업데이트 결과에 따른 후속 작업(실패 시 장바구니 리스트에서 상품 삭제): 비즈니스 로직 계층에서 수행
장바구니 상태 보여줌: UI 계층에서 수행
이렇게 수행된다.

계층 아키텍처는 데이터베이스 주도 설계를 유도한다.
계층 아키텍처를 사용하면 개발을 할 때 데이터베이스 위주로 사고를 하게 된다는 뜻이다.
예를 들면 다음과 같은 순서로 개발을 하는 것이다.
먼저 해당 기능에 필요한 데이터를 기준으로 데이터베이스 테이블을 구성한다.
그리고 해당 테이블에 데이터를 삽입하거나 가져오는 쿼리를 작성한다.
쿼리를 통해 가져온 데이터를 토대로 어떤 기능을 수행하도록 하는 코드를 작성한다.
이러한 방식이 나쁜 것은 아니지만 기능의 목적에 집중하는 것이 아닌 데이터에 집중하게 되어 코드를 보았을 때 기능의 목적을 파악하기 어렵다.
또한 개발자가 편한 사고 방식이므로 개발자가 아닌 사람과 소통을 할 때 오류가 발생할 수 있다.
계층 아키텍처가 데이터베이스 주도 설계를 유도한다고 해서 도메인 주도 설계를 적용할 수 없다는 뜻은 아니니 이 점을 유의해야 한다.

Clean Architecture

2012년에 Robert C. Martin(a.k.a. Uncle Bob)에 의해 소개되었다.
Onion Architecture(양파 아키텍처)와 도메인 주도 설계의 핵심을 합한 아키텍처이다.
어니언 아키텍처는 비즈니스 로직과 인터페이스 어댑터(외부 시스템과 통신하기 위해 사용하는 것)를 분리하는 것이 핵심인 아키텍처이다.
Domain Layer, Application Layer, User Interface Layer, Infrastructure Layer로 분리되어 있다.

  • Domain Layer - 엔터프라이즈 비즈니스 규칙을 정의하는 Entity가 존재한다.
  • Application Layer - 비즈니스 역할을 수행하는 Use Case가 있다.
  • User Interface Layer - 데이터를 가져오는 Repository와 User Interface를 다루는 Controller, Presenter가 함께 존재하는 계층이다.
  • Infrastructure Layer - 어떤 DB, 어떤 프레임워크를 사용하는지와 같은 매우 구체적으로 구현된 부분이다.

도메인 계층과 어플리케이션 계층이 구분되기 때문에 패키지와 파일 구조를 살펴보는 것만으로도 어떠한 기능이 수행되는지 파악하기 쉽다.

의존성은 도메인 계층으로 향한다.
도메인 계층은 사용 당하기만 한다.
어플리케이션 계층은 도메인 계층에 의존해야 하며 어떠한 계층도 데이터(여기에선 Repository)에 의존하지 않는다.
어플리케이션 계층이 데이터를 모르는데 어떻게 비즈니스 로직을 수행할까?
이를 위해 Dependency Inversion Principle(의존성 역전 원칙)을 이용한다.
어플리케이션 계층은 레포지토리의 인터페이스를 참조하고, 실제 레포지토리의 구현체는 User Interface 계층에 작성하여 사용하는 것이다.
만약 어플리케이션 계층이 데이터에 의존하였다면 A 레포지토리 대신 B 레포지토리를 써야 하는 경우에 어플리케이션 계층에서 A 레포지토리를 사용했던 부분을 B 레포지토리로 바꿔줘야 겠지만 인터페이스를 참조하여 개발했다면 B 레포지토리가 해당 인터페이스의 구현체인 경우 어플리케이션 계층의 코드 변경없이 그대로 사용할 수 있다.
확장성이 높아진 것이다.
다만 이렇게 인터페이스를 작성하게 되면 계층 아키텍처에 비해 파일 개수가 많아지게 된다.

Differences

계층 아키텍처는 Data Centric(데이터 중심) 아키텍처이기 때문에 비즈니스 의도를 반영하지 않는다.
데이터 중심으로 이름을 붙이고 Use Case뿐만 아니라 모든 것들이 데이터 중심으로 정해진다.
클린 아키텍처는 도메인이 중심이다.
프로그램을 만드는 이유가 특정 문제를 소프트웨어로 해결하기 위함이니 해결할 문제를 중점으로 두고 프로그램을 설계한다는 것이다.

계층 아키텍처는 Business Logic 계층이 비즈니스 규칙과 역할을 모두 담당한다.
그러나 클린 아키텍처에서는 이를 Domain과 Application 계층으로 분리한다.
SOLID 원칙의 관점에서 보면 계층 아키텍처의 Business Logic 계층은 여러 책임을 가지게 되므로 단일 책임 원칙에 위배된다.
SOLID 원칙을 지키고자 한다면 클린 아키텍처와 같이 비즈니스 규칙과 역할을 분리하는 것이 옳을 것이다.

Conclusion

아키텍처를 사용하는 목적은 전체 개발 프로세스를 간단하게 만들기 위함이다.
특히 아키텍처를 사용하면 유지보수 비용을 줄이는데 용이하다.
더 자세히 말하면 특정 인프라에 대한 의존성을 줄여서(관심사를 분리해서) 변경이 용이하고 확장성이 높은 코드를 만들어 코드를 이해하고 수정하는 시간을 절감하는 것이다.

계층 아키텍처는 구조가 단순해서 추가적인 지식없이 쉽게 구조를 파악할 수 있다는 장점이 있지만 실제로 어떤 기능이 포함되어 있는지 파악하기 어렵다는 단점이 있다.
클린 아키텍처는 프로젝트가 어떤 일을 하는지 파악하기 쉽다는 장점이 있지만 패키지 구조가 복잡하고 계층 분리를 위해 인터페이스를 작성해야 하기 때문에 단순한 기능을 구현할 때도 많은 양의 코드를 작성해야 한다는 단점이 있다.
각 아키텍처의 장단점을 비교해보았을 때 규모가 작은 프로젝트의 경우에는 빠른 개발을 위해 구조가 단순하고 익숙한 계층 아키텍처를 선택하는 것이 괜찮아 보인다.
규모가 크고 여러 인원이 진행하는 프로젝트는 클린 아키텍처를 적용하는 것이 추후 유지보수를 진행할 때 도움이 될 것이다.

클린 아키텍처 설명을 처음 봤을 때는 일단 용어가 무슨 뜻인지 모르거나 헷갈려서 이해하는데 어려움이 있었다.
어떤 사람은 Application 계층이라 하고 어떤 사람은 Use Case 계층이라 해서 뭐가 맞는 건지 혼란스러웠는데 그냥 혼용해서 사용하는 구나 하고 받아들이니 그때부턴 괜찮았다.
그러다 다시 ‘어니언 아키텍처’같은 모르는 개념이 나오면 그것에 대해 공부하고 또 그 설명에서 모르는 개념이 나와서 공부하고 이걸 계속 반복했다.
마치 사칙연산도 모르면서 분수의 나눗셈을 이해하려한 것 같았다.
계속해서 학습하고 용어들도 눈에 익고 익숙해지니 다시 클린 아키텍처 설명을 봤을 때 내용이 이해가 가기 시작했다.
그때부턴 실제 개발을 할 때는 어떻게 쓰이는 것인가를 계속해서 생각하고 찾아보며 정말 개념을 완전히 이해하기 위해 관련 영상과 글을 반복해서 읽었다.
그 결과 이렇게 포스트를 작성할 수 있게 되었다.
글에 다소 부족한 점이 있을 수는 있지만 나중에 이 글을 다시 읽었을 땐 그 점을 보완할 수 있으리란 생각이 든다.
안드로이드 앱의 경우 구글에서 앱 개발 시 권장하는 아키텍처를 설명한 글이 있기 때문에 다음 포스트에는 해당 문서를 읽고 정리할 계획이다.
다음 포스트까지 작성 후에 현재 진행하고 있는 OlymPos에 어떤 아키텍처를 사용할 것인지 선정하여 적용할 것이다.

Reference:
  1. The Great N-layer vs Clean Architecture Debate
  2. Introduction to Clean Architecture & Problems with Layered Architecture
  3. 요즘 핫한 Clean Architecture 왜 쓰는 거야?