본문 바로가기
시스템아키텍처

레임워크 주도 개발의 극복: 클린 아키텍처의 의존성 규칙과 포트 앤 어댑터(헥사고날)

by 매일기술사 2026. 4. 13.
기술사 학습노트 소프트웨어 공학 소프트웨어 아키텍처
SOFTWARE ARCHITECTURE · 정보관리기술사 / 컴퓨터시스템응용기술사

소프트웨어 의존성 제어의 결정체: 클린 아키텍처(Clean Architecture) 완벽 해부

로버트 C. 마틴(Uncle Bob)이 제안한 클린 아키텍처의 본질, 아키텍처의 생명줄인 의존성 규칙(Dependency Rule), 4대 계층 구조(Entities, Use Cases, Adapters, Frameworks) 및 의존성 역전 원칙(DIP)을 활용한 제어 흐름의 분리 메커니즘을 심층 분석한다.

정보관리기술사 컴퓨터시스템응용기술사 소프트웨어아키텍처 클린아키텍처 의존성역전 DIP 헥사고날 솔리드원칙 엔티티 유스케이스
Ⅰ. 아키텍처 부식의 극복, 클린 아키텍처(Clean Architecture) 개요

가. 데이터베이스 중심 설계와 전통적 계층형(Layered) 아키텍처의 한계

전통적인 3계층(Presentation - Business - Data Access) 아키텍처는 시간이 지남에 따라 비즈니스 로직이 데이터베이스(DB)나 특정 프레임워크 기술에 강하게 종속되는 현상을 낳았다. 이로 인해 '프레임워크 주도 개발(Framework-driven Development)'이 되어버려, DB를 교체하거나 UI를 웹에서 모바일로 변경할 때 핵심 비즈니스 로직까지 뜯어고쳐야 하는 심각한 아키텍처 부식(Architecture Erosion)이 발생했다.

나. 클린 아키텍처의 본질: '관심사의 완벽한 분리(Separation of Concerns)'

  • 비즈니스 규칙의 격리: 애플리케이션의 핵심 목적(유스케이스와 엔티티)을 프레임워크, UI, 데이터베이스 등 변경되기 쉬운 '세부사항(Details)'으로부터 완벽하게 격리한다.
  • 독립성과 테스트 용이성: 비즈니스 규칙은 외부 요소에 전혀 의존하지 않으므로, DB나 웹 서버 없이도 독립적으로 비즈니스 로직에 대한 단위 테스트(Unit Test)를 100% 수행할 수 있다.
Ⅱ. 클린 아키텍처 핵심 구조와 의존성 역전(DIP) 메커니즘

가. 동심원 계층 구조 및 의존성 규칙 (Dependency Rule) 시각화

클린 아키텍처의 가장 중요한 단 하나의 규칙은 "소스 코드의 의존성은 반드시 바깥쪽(세부사항)에서 안쪽(고수준 정책)으로만 향해야 한다"는 의존성 규칙(Dependency Rule)이다.

Frameworks & Drivers (DB, Web, UI, Devices) Interface Adapters (Controllers, Gateways, Presenters) Use Cases Entities Dependency Rule 제어 흐름과 의존성 역전 (DIP) 교차점 Adapters Adapters Use Cases Controller <Interface> Input Port Use Case Interactor <Interface> Output Port Presenter 제어 흐름 (Flow of Control) ★ 제어 흐름은 바깥으로 나가려 하지만, 인터페이스를 통한 DIP로 소스 의존성은 안쪽을 향함

나. 의존성 역전 원칙 (DIP: Dependency Inversion Principle)의 마법

애플리케이션이 실행되려면 제어 흐름(Control Flow)은 필연적으로 [Controller ➔ Use Case ➔ Presenter(UI)] 순서로 바깥쪽 계층으로 흘러가야 합니다. 하지만 이대로 코드를 작성하면 Use Case가 바깥 계층인 Presenter에 의존하게 되어 '의존성 규칙'을 위반합니다.
클린 아키텍처는 이를 해결하기 위해 Use Case 계층 내부에 출력 포트(Output Port)라는 인터페이스를 선언하고, 바깥 계층의 Presenter가 이 인터페이스를 상속(구현)하게 만듭니다. 결과적으로 소스 코드의 의존성 방향이 제어 흐름과 반대 방향(역전)이 되어 완벽한 계층 보호가 달성됩니다.

Ⅲ. 클린 아키텍처의 4대 핵심 계층 (Layers) 상세 분석
계층명 (Layer) 핵심 구성요소 및 역할 변경의 빈도 및 독립성 수준
엔티티
(Entities)
전사적(Enterprise) 핵심 비즈니스 규칙을 캡슐화한 객체이다. 메서드를 가진 객체일 수도 있고, 일련의 데이터 구조와 함수 모음일 수도 있다. (최상위 정책) 외부의 변경(보안 결함, UI 변경 등)에 의해 절대 변하지 않는 가장 견고하고 독립적인 중심 계층이다.
유스케이스
(Use Cases)
애플리케이션에 특화된(Application-wide) 비즈니스 규칙을 포함한다. 시스템의 모든 유스케이스(동작 흐름)를 오케스트레이션하며, 엔티티에게 데이터 조작을 지시한다. (고수준 정책) 데이터베이스나 프레임워크의 변경에 영향을 받지 않는다. 오직 해당 애플리케이션의 '기능'이 변경될 때만 수정된다.
인터페이스 어댑터
(Interface Adapters)
유스케이스와 외부 프레임워크 사이의 데이터 포맷 변환기(Adapter)이다. Controller, Presenter, Gateway가 여기에 속하며 데이터를 웹용(JSON 등)이나 DB용(SQL)으로 상호 변환한다. (저수준 세부사항) 내부(Use Case)의 데이터를 외부(Web, DB)에 맞게 가공하는 역할이므로, 외부 프레임워크의 스펙에 맞춰 자주 변경될 수 있다.
프레임워크 및 드라이버
(Frameworks & Drivers)
데이터베이스, 웹 프레임워크, UI, 외부 API 등 시스템을 구성하는 가장 외곽의 구체적인 세부사항(Details) 기계 장치들이다. (최하위 세부사항) 기술 트렌드나 벤더 종속성에 따라 언제든 쉽게 교체 가능(Pluggable)해야 하는 소모성 계층이다.
Ⅳ. 아키텍처 경계(Boundary)와 유사 설계 철학의 융합

가. 헥사고날 아키텍처 (Ports and Adapters)와의 철학적 동질성

알리스테어 콕번(Alistair Cockburn)이 창안한 헥사고날 아키텍처(포트 앤 어댑터)나 제프리 팔레르모의 어니언 아키텍처(Onion Architecture) 모두 클린 아키텍처와 본질적인 목표를 완벽히 공유한다. 외부 시스템(DB, UI)은 플러그인처럼 교체 가능해야 하며, 내부는 포트(인터페이스)를 통해서만 외부의 어댑터(구현체)와 통신해야 한다는 의존성 역전의 철학을 궤를 같이한다.

나. 경계(Boundary)를 횡단하는 데이터 구조 제어

경계를 가로질러 데이터를 전달할 때는 반드시 단순하고 독립적인 데이터 구조(DTO, Data Transfer Object)만을 사용해야 한다. 엔티티 객체나 데이터베이스의 ORM(예: JPA Entity, Hibernate Row) 객체를 그대로 바깥 계층이나 안쪽 계층으로 넘기면, 안쪽 원이 바깥쪽 원의 데이터 포맷을 알아버리게 되어 의존성 규칙이 처참하게 붕괴된다.

Ⅴ. 실무 도입의 트레이드오프(Trade-off)와 마이크로서비스(MSA)

가. 클린 아키텍처 도입 시의 치명적 단점 및 고려사항

  • 초기 개발 속도 저하와 복잡성 증가: 완벽한 격리를 위해 각 계층 간의 데이터 변환(DTO 매핑) 및 무수히 많은 인터페이스(Port)를 작성해야 하므로 보일러플레이트(Boilerplate) 코드가 폭발적으로 증가한다.
  • 오버엔지니어링(Over-engineering)의 위험: 비즈니스 로직이 매우 단순한 CRUD 중심의 소규모 애플리케이션에 클린 아키텍처를 도입하는 것은 배보다 배꼽이 더 큰 오버엔지니어링이 될 수 있다. 시스템의 복잡도와 생명주기를 고려한 전략적 선택이 필수적이다.

나. 마이크로서비스 아키텍처(MSA)와의 시너지

클린 아키텍처는 단일 모놀리식 시스템 내부의 컴포넌트 경계를 나누는 데 그치지 않습니다. 현대의 마이크로서비스 아키텍처(MSA) 환경에서, 각 마이크로서비스 내부는 클린 아키텍처 또는 헥사고날 아키텍처로 구현되어 외부 API, 이벤트 브로커(Kafka), 이기종 DB 등으로부터 자신의 핵심 비즈니스 도메인을 독립적으로 방어하는 가장 강력한 표준 설계 패턴으로 자리 잡았습니다.

블로그: 기술사 학습노트 · imt-log.tistory.com