들어가며

처음 소프트웨어 아키텍처를 공부할 때, “클린 아키텍처”는 “잘 설계된 모든 아키텍처”를 이르는 말이라고 생각했던 기억이 난다. “클린 아키텍처”는 로버트 C. 마틴이 그의 블로그 글에 사용하면서 유명해졌다. 그는 클린한 소프트웨어 아키텍처는 새로운 것이 아니라 여러 소프트웨어 엔지니어에 의해 여러 해 동안 홍보되었음을 명확하게 언급하고 있지만 그럼에도 불구하고 “클린 아키텍처”라는 용어는 명확한 정의와 구조를 제공하면서 많은 개발자들에게 큰 영향을 미쳐온 것 같다. 로버트 C. 마틴은 소프트웨어 아키텍처가 단순히 코드가 잘 동작하는 것만을 목표로 하는 것이 아니라, 유연성, 테스트 용이성, 독립성을 확보하는 데 초점을 맞춰야 한다고 강조했다. 즉, 비즈니스 로직이 외부 의존성에 영향을 받지 않고, 기술적 변화에도 쉽게 적응할 수 있는 구조를 만들어야 한다는 것이다.

클린 아키텍처의 핵심은 여러 계층으로 나뉜 시스템 설계에서 의존성의 방향을 통제하는 것이다. 바깥 계층(예: UI, 데이터베이스 등)은 안쪽 계층(핵심 비즈니스 로직)을 참조할 수 있지만, 그 반대는 불가능하다. 이를 통해 외부 프레임워크나 라이브러리의 변화가 시스템의 핵심 로직에 미치는 영향을 최소화할 수 있다. 이런 구조는 유지보수성을 높이고, 테스트를 용이하게 하며, 장기적으로 시스템의 확장 가능성을 보장하는 데 기여한다.

이 포스트는 로버트 C.마틴의 클린 아키텍처를 읽고 적용하기 위한 자료를 찾던 중 “clean-architectures-in-python”이라는 책을 읽고 정리한 내용이다. 이번 포스트에서는 클린 아키텍처의 개념과 구성요소에 대해 간단하게 정리하고 다음 포스트에서는 파이썬으로 구현한 클린 아키텍처에 대해 자세히 살펴보았다. 파이썬으로 구현한 클린 아키텍처와 구체적인 구현이 궁금하다면 다음 포스트나, 을 읽어보기를 추천한다.

1. 클린 시스템에서의 일상

1) 데이터 흐름

2024-09-05-python-clean-01.png

2) 계층형 아키텍처의 장점

(1) 데이터 흐름의 일관성
2024-09-05-python-clean-02.png
데이터는 각 계층을 거치면서 명확한 방향으로 흐르기 때문에, 데이터의 출처와 변화를 추적하기가 용이하다. 이를 통해 데이터 처리의 복잡성을 줄이고, 오류를 방지할 수 있다.
위 이미지에서 처럼 웹 프레임워크를 CLI로 대체하더라도, 데이터의 흐름은 변하지 않는다.

(2) 테스트의 용이성
2024-09-05-python-clean-03.png
각 계층이 독립적이기 때문에, 계층별 격리와 테스트가 용이하다.

2. 클린 아키텍처의 구성요소

1) 분할 통치

잘 설계된 시스템은 원할한 제어를 주요 목표로 한다. 책임이 명확할 때 시스템은 더 잘 동작한다. 시스템에서 순서와 제어를 다루는 좋은 방법은 시스템을 하위 시스템으로 분할하고 그 사이에 명확하고 엄격한 경계를 설정하여 데이터 교환을 제한하는 것이다. 이는 하나의 복잡한 시스템보다 상호 연결된 작은 시스템 집합을 다루는 것이 더 간단하다는 정치적 개념(분할 통치)의 확장이다.

2) 데이터 타입

소프트웨어 시스템을 고려할 때에는 타입과 데이터 포맷(‘언어’)을 정의하는 부분을 이해하고, 종속성이 구현자에게 방해가 되지 않는지 확인해야 한다.

”””
도매업체에서 상품을 구매하여 진열대에 진열하고 고객에게 판매하는 상점의 첫 번째 예로 돌아가 보자. 여기에서 두 컴포넌트 사이에는 분명한 종속성이 있다. 데이터(‘상품’)는 ‘도매’라는 컴포넌트에서 ‘상점’이라는 컴포넌트로 흐른다. 따라서 상점은 도매에 의존한다. 상점의 선반 크기는 도매에서 정의하는 품목(타입)의 크기에 따라 달라지며, 이는 이미 설정한 종속성을 따른다.

만약 상품의 크기를 상점에서 정의한다면, 갑자기 우리는 이미 설정한 종속성에 반대되는 또 다른 종속성이 발생하게 되고 도매가 상점에 종속된다. 소프트웨어 시스템에서 이는 순환 의존성이 아니다. 첫 번째는 개념적 의존성이며, 두 번째는 컴파일 시점에서 언어 수준에서 발생한다. 어쨌든 두 개의 상반된 종속성을 갖는 것은 확실히 혼란스럽고 대체하기 어렵다. “주변장치”와 같은 컴포넌트가 상점을 대체할 수는 없다. “””
위 부분이 구체적으로 그려지지 않아서, 클린 아키텍처 책을 한 번 더 보고 정리하려고한다.
컴포넌트 종속성이 있는 A,B 컴포넌트가 있을 때(A -> B) B에서 데이터 타입을 먼저 정의하면 안된다는 것인가…?

https://wikidocs.net/195223

3) 주요 4계층

2024-09-05-python-clean-04.png
(1) 엔터티
클린 아키텍처의 이 계층에는 시스템이 상호 작용하는 데 필요한 모든 것, 즉 특정 표현이 필요할 만큼 충분히 복잡한 도메인 모델의 표현이 포함된다. 엔티티 계층은 외부 계층이 데이터를 교환하는 데 사용할 수 있는 견고한 기반 타입을 제공하며, 이는 비즈니스의 어휘라고 할 수 있다.

(2) 유스케이스
앞서 말했듯이 클린 시스템에서 가장 중요한 부분은 시스템 자체의 핵심 존재 이유인 비즈니스 규칙을 구현하는 유스케이스이다. 유스케이스는 애플리케이션에서 발생하는 프로세스로써, 도메인 모델을 사용하여 실제 데이터를 다룬다. 유스케이스는 가능한 한 작아야 한다.

(3) 게이트웨이
이 계층에는 비즈니스 규칙을 구현하지 않는 서비스에 대한 공통 접근 모델을 다룬다. 즉 외부 시스템에 대한 인터페이스를 정의하는 구성 요소가 포함되어 있다. 데이터 스토리지가 대표적이다.

(4) 외부시스템
이 계층은 이전 계층에서 정의된 인터페이스를 구현하는 컴포넌트로 채워진다. 시스템에서 어떤 인터페이스의 여러가지 구현체를 동시에 지원하고 싶은 경우가 있을 수 있으므로, 동일한 인터페이스가 하나 이상의 구체적인 컴포넌트에 의해 구현될 수 있다.

4) 계층간 통신

클린 아키텍처에서는 계층이 깊어질수록 콘텐츠는 더 추상적이다. 내부 계층에는 비즈니스 개념의 표현이 포함되어 있고 외부 계층에는 실제 구현에 대한 구체적인 세부 정보가 포함되어 있다. 같은 레이어에 있는 요소 간의 통신은 제한이 없지만 다른 레이어에 할당된 요소와 통신하려면 한 가지 간단한 규칙을 따라야 한다. “안쪽으로 대화할 때는 단순한 구조를, 바깥쪽으로 대화할 때는 인터페이스를 사용하라.”

5) API와 회색 지대

계층 간 분리와 각 계층의 콘텐츠는 항상 고정되어 불변하는 것이 아니다. 잘 설계된 시스템은 성능이나 기타 특정 요구사항과 같은 현실적인 문제에도 대응할 수 있어야 한다. 아키텍처를 설계할 때 “무엇이 어디에 왜 필요한지”를 아는 것은 매우 중요하며, 이는 규칙을 “완화할”1 때 더욱 중요하다. 우리가 접하는 많은 문제에는 정답을 흑백으로 가를 수 없는 것들이 많다. 수많은 결정사항이 “회색 지대”에 있다. 즉 주어진 장소에 무언가를 배치하는 이유를 정당화하는 일은 구현하는 사람의 몫이다.

이어지는 글

[Architecture] 파이썬으로 구현하는 클린 아키텍처 (2)python 프로젝트 구현하기

Reference

Clean Architecture in Python