
사이드 프로젝트에서 DDD 방법론을 이용해서 프로젝트를 진행할 예정이다. 그런데 아키텍처 선택에 대한 문제가 있기에 layered와 hexagonal 2개를 비교하려고 한다. (clean architechture는 논외로 치고 글을 작성했다)

Layered Architecture는 소프트웨어 시스템을 논리적인 책임에 따라 수직적인 계층으로 분리하여 설계하는 가장 보편적인 아키텍처이다. spring boot로 프로젝트를 진행하였다면 다들 Layered를 사용해본 경험을 가지고 있을 것이다. (Controller, Service, Repository, Entity 4개로 계층을 나눠서 사용했기에 Layered로 사용했을 거라고 추측하였다)
Infrastructure, Application, Domain, Presentation
src/main/java/com/example/project/
├─ presentation/
│ └─ article/
│ ├─ ArticleController.java
│ └─ ArticleDto.java
│
├─ application/
│ └─ article/
│ └─ ArticleService.java
│
├─ domain/
│ └─ article/
│ ├─ Article.java
│ ├─ ArticleRepository.java ← interface
│ └─ ArticleService.java ← DomainService(선택)
│
└─ infrastructure/
└─ article/
├─ JpaArticleRepository.java ← Repository 구현체
└─ ArticleEntityMapper.java ← JPA 엔티티 변환

hexagonal은 비즈니스 로직을 중심에 두고, 외부 세계와의 모든 상호작용을 포트(Port)와 어댑터(Adapter)라는 표준화된 인터페이스를 사용하는 아키텍처이다.
모든 의존성은 안쪽을 향함(의존성 역전의 원칙) : 비즈니스 코어는 외부 기술(예: 특정 DB)에 대해 전혀 알지 못해야 한다. 코어는 자신이 필요한 기능을 인터페이스(포트)로만 정의하고, 실제 구현은 외부의 어댑터가 담당한다.
src/main/java/com/example/project/
├─ domain/ // 1. Core: Domain Layer (가장 중심, 순수한 비즈니스 로직)
│ └─ article/
│ └─ Article.java // 핵심 도메인 모델, 비즈니스 규칙 포함
│
├─ application/ // 2. Application Layer (Use Case 정의 및 구현)
│ ├─ port/
│ │ ├─ in/
│ │ │ └─ ArticleCommandPort.java // [인바운드 포트] 외부 요청을 처리하는 인터페이스 정의
│ │ └─ out/
│ │ └─ ArticleLoadPort.java // [아웃바운드 포트] DB 접근 등 외부 호출을 위한 인터페이스 정의
│ └─ service/
│ └─ ArticleCommandService.java // [Use Case 구현체] ArticleCommandPort 인터페이스 구현
│
└─ adapter/ // 3. Adapters Layer (인프라 및 입출력 기술 의존성 관리)
├─ in/
│ └─ web/
│ ├─ ArticleWebAdapter.java // [인바운드 어댑터] Spring Controller 역할. Port 호출
│ └─ ArticleRequest.java // Web DTO
└─ out/
└─ persistence/
├─ JpaArticleAdapter.java // [아웃바운드 어댑터] ArticleLoadPort 인터페이스 구현 (DB 연동)
└─ JpaArticleEntity.java // JPA 전용 엔티티
글을 읽고 또 읽어도 잘 모르겠다는 생각이 들었기에 코드를 직접 만들어 보기로 하였다. 숙소 예약 기능을 가진 프로젝트를 생성하고 아키텍처를 비교해 보겠다.
공부한 프로젝트 (코드와 폴더 구조에대해서 의견을 주시면 긍정적으로 반영하겠습니다. )
프로젝트는 3개에 도메인 기능이 있는데 [숙소 관리,예약 관리, 유저 관리]를 중심으로 구현하였다.
두 아키턱처에서 파일 개수가 나는 이유는 Layered의 Service 1개 역할을 Hexagonal에서는 UseCase Port + Service + Repository Port로 분리하고, 추가로 DTO, Mapper, Adapter를 더해서 총 7-10개 파일이 더 필요하기 때문이다.
| Feature | Layered Files | Hexagonal Files | Increase |
|---|---|---|---|
| Lodging | 4 files | 11 files | +175% |
| Reservation | 4 files | 14 files | +250% |
| User | 3 files | 13 files | +333% |
| Application Entry | 1 file | 1 file | - |
| Total | 14 files | 38 files | +171% |
Hexagonal은 구조를 통해 강제적으로 SOLID 원칙을 준수하도록 만드는 방법이라고 느껴진다.환경을 통해서 개발자를 가이드하는 것, 이것이 좋은 아키텍처가 아닐까라는 생각이 들었다.
하지만 동시에 "Hexagonal은 모든 프로젝트에 실질적인 도움을 줄까?"라는 의문도 들었다. Hexagonal Architecture, 진짜 하실 건가요?와 okky 커뮤니트를 읽고 또 생각에 잠긴다.
결론은 또 케바케다. 결국 아키텍처는 현재 팀의 상황과 프로젝트 특성에 맞춰 선택해야 하며, "무조건 Hexagonal이 좋다" 또는 "과도하다"는 이분법적 사고보다는 트레이드오프를 이해하고 의식적으로 선택하는 것이 중요하다.
개인적으로 이번 조사를 통해 느낀 점은, Hexagonal Architecture는
"초기 비용을 지불하고 장기 이익을 얻는 투자"라는 것이다. 프로젝트가 그만한 투자 가치가 있는지 판단하는 것이 핵심이다.