
목차
- 소프트웨어 아키텍처란?
- 레이어드 아키텍처
- 클린 아키텍처
- 헥사고날 아키텍처
- 마치며
소프트웨어 아키텍처
아키텍처
- 어떤 대상의 구성과 동작원리, 구성 요소간의 관계 및 시스템 외부환경과의 관계를 설명하는 하나의 설명서
소프트웨어 아키텍처
- 소프트웨어 구성요소들 사이 관계를 표현하는 설명서
소프트웨어가 제공하는 가치
구조가 더 중요하다
왜 구조가 중요할까?
- 소프트웨어 비용과 관련됨
- 개발 초기 단계 : 개발 비용이 더 높음
- 개발 완료 단계 : 변화하는 소프트웨어 유지보수
- 장기적으로 봤을 때 기능 개발 비용 > 유지 보수 비용
기능 좋음 + 구조 부족 vs 기능 부족 + 구조 좋음
| 비교 | 특징 |
|---|
| 기능 좋음 + 구조 부족 | 당장은 좋지만 수정 비용이 너무 크다. 언제 버려질 지 모른다. |
| 기능 부족 + 구조 좋음 | 당장은 부족하지만 수정하는데 비용이 적다. 개선, 확장에 유연하다. |
좋은 구조를 만드는 방법
아키텍처 패턴
- 계층형 아키텍처 / 클린 아키텍처 / 헥사고날 아키텍처
- 아키텍처 적용함으로써 소프트웨어를 통해 이루고자 하는 핵심 목표인 도메인을 지킬 수 있음
- 외부 요소인 UI, DB, API 같은 것에 도메인이 의존하지 않도록 도메인 보호
레이어드 아키텍처
- 관심사가 같은 코드들을 계층으로 그룹화
Presentation, Application, Persistence 계층으로 나눠 사용하고 필요에 따라 계층을 추가해서 사용할 수 있음
특징
- 계층화로 인한 분리된 책임
- 편의에 따라 여러 계층 추가 가능
- 구조가 쉽고 단순하고 익숙
- 데이터베이스 주도 설계가 될 수 있음
문제점
- Presentation, Application, Persist 순 의존성 발생
- 상위 레이어(Presentation Layer)가 하위 레이어(Persistence Layer)를 알 수 있는 상황을 만들게 됨
- 하위 레이어 변경이 상위 레이어 변경을 영향을 주게 됨
- Persistence Layer의 변화가 Application Layer의 변화를 유발하고 프레젠테이션 계층까지 수정이 필요해짐 (의존성을 가짐)
- 한 계층의 변화가 다른 계층까지 영향을 주기 때문에 코드 변경이 어려워짐
클린 아키텍처
- 의존성 역전을 통해 도메인이 중심
- 프로젝트 전체가 DB가 아닌 도메인에 의존하게 하는 방법으로 문제 해결

특징
- 핵심 규칙을 담고 있는 도메인이 중심
- 도메인이 세부 사항에 의존하지 않는다.
- 세부사항 : 입출력 장치, 디비, 웹시스템, 서버, 프레임워크, 통신 프로토콜 등
- 익숙하지 않을 수 있고 레퍼런스가 적다.
구분

Entity와 Use Cases가 있는 계층 (안쪽)
- 비즈니스 로직을 캡처한 계층
- 외부 요소에 대해 절대로 알면 안됨
외부요소가 존재하는 계층 (밖)
구성
Entity 레이어

- 가장 핵심적인 비즈니스 로직이나 규칙을 담고있는 레이어
- 엔터프라이즈 비즈니스 규칙(Entities)
- 애플리케이션의 핵심적인 엔티티나 도메인 객체
- 비즈니스 로직이나 규칙을 나타내며 외부 요소에 대한 어떠한 의존성도 없다.
- 대부분 프로젝트에서 도메인 패키지에 들어있는 것들
Use Case 레이어

- 애플리케이션 비즈니스 규칙 (Use Cases)
- 특정 비즈니스 로직을 포함하며 데이터 저장, UI 등은 관심 없다.
- 보통 Repository에서 객체를 받아와서 특정 행위를 하고 업데이트 하는 부분 처리
Adapter 레이어

- 인터페이스 어댑터(Interface Adapters)
- 데이터를 애플리케이션(Use Case)에서 사용하는 형태로 변환하거나 내부에서 사용하는 데이터를 외부에 적합한 형태로 변환
Infrastructure 레이어
클린 아키텍처는 추상적이다.

헥사고날 아키텍처

특징
- 큰 비즈니스 가치를 가지고 있는 도메인 모델에 큰 관심
- 레퍼런스가 클린 아키텍처에 비해 많다.
- 포트와 어댑터를 구성하고 관리하는데 복잡성이 따른다.
- 도메인에 라이브러리를 직접 활용하기 어렵다.
구성
도메인 모델 (Domain Model)

- POJO로 이루어진 Entity와 Use Case는 클린 아키텍처의 Entity와 Use Case와 유사
- POJO : Plain Old Java Object의 약자로 순수한 오래된 자바 객체
- 즉 Java로 생성하는 순수한 객체
- Java나 Java 스펙에 정의된 것 이외에 다른 기술이나 규약에 얽메이지 않아야 함
- 특정 환경에 종속적이지 않아야 함(특정 프레임워크나 웹 기술 담고있는 클래스 또는 인터페이스 사용X)
- 출처 : [Spring] POJO란 무엇인가?
- 어플리케이션의 핵심 기능, 비즈니스 로직이나 규칙을 캡슐화
포트 (Port)

어댑터 (Adapter)

- 특정 포트에 연결되어 외부와 도메인간 통신을 가능하게 한다.
- 외부 요소(웹 요청, 데이터베이스 등) 실제 통신 발생
- 포트를 구현하기도 하며 포트를 통해 Use case를 직접 호출하기도 합니다.
다른 방식으로 보는 방법
입력포트 & 어댑터

- 입력포트는 동작을 유발하는 외부 요청 처리
- Use case를 호출하는 입력 포트 입력 어댑터
출력포트 & 어댑터

- Use case로부터 호출되어 외부에 결과를 전달하는 것들을 출력 포트, 출력 어뎁터라 볼 수 있음
좀 더 직관적 그림

헥사고날 아키텍처 어떻게 적용할까?
이 부분은 다른 실제 코드 예시 기반 새 포스팅으로 작성하겠습니다.
마치며
큰 프로젝트 사례 - 헥사고날 아키텍처 적용 타 유튜브 영상
- 라인 : 1.15배 / 파일 수 : 1.5배 / 패키지 수 4.28배 증가
- 레이어드 아키텍처와 비교해서 코드 양과 복잡도 증가
클린 아키텍처를 적용하면 항상 좋은가?
- 의존 관계가 복잡하지 않다면 레이어드 아키텍처가 좋은 방안일수도 있음
이럴 때 고려해보세요.
- 대규모 프로젝트 진행할 때
- 프로젝트 일원 모두 클린 아키텍처를 이해할 때
- 외부 요소가 변화가 잦을때