Files
llm-wiki/raw/company-tech-blogs/woowahan-hexagonal-multimodule.md
T

111 lines
8.8 KiB
Markdown

---
title: "Spring Boot Kotlin Multi Module로 구성해보는 헥사고날 아키텍처 — 우아한형제들"
source_type: company-tech-blog
url: https://techblog.woowahan.com/12720/
archive_url:
status: raw
confidence: medium
tags: [ca-transaction-boundary, hexagonal, woowahan, multi-module, kotlin]
related_branches: [feature-application-port-usecase-contract, feature-transaction-concurrency-contract]
related_projects: [ca-skeleton-operational-contract]
created: 2026-05-22
last_reviewed: 2026-05-27
---
# 우아한형제들: Spring Boot Kotlin Multi Module 헥사고날 아키텍처
> Layer: `raw/company-tech-blogs/` — 우아한형제들 기술블로그의 **원문 발췌·출처 기록**. 헥사고날을 multi-module 로 분리한 국내 대기업 사례 (4 layer hexagon).
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성. 원본은 raw에 영구 보관.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-application-port-usecase-contract]] | application 모듈이 framework 의존을 받지 않도록 multi-module 로 격리한 국내 사례 — ca-tmpl 의 TransactionPort 결정과 호환 |
| [[raw/branch-notes/feature-transaction-concurrency-contract]] | Topic 2 — Transaction Boundary 의 모듈 분리 보완 (대체 아님) 사례 |
| [[raw/project-notes/ca-skeleton-operational-contract]] | §14. Transaction / Concurrency Contract — 국내 대기업 헥사고날 비교군 |
## 컨텍스트 / 왜 저장했는지
ca-tmpl 의 TransactionPort 결정에 대한 **국내 대기업 비교군**. 우아한형제들이 헥사고날을 multi-module 로 분리할 때 어디까지 Spring 의존을 응용 계층 밖으로 밀어내는지, 그리고 트랜잭션 처리는 어디에 위치시키는지 확인.
## 출처 / Source
- 원본 URL: https://techblog.woowahan.com/12720/
- 아카이브 URL: (미수집)
- 저자 / 조직: 우아한형제들 기술블로그
- 발행일: 게시일 미명시
- 마지막 확인일: 2026-05-27
## 핵심 인용 / Key quotes (verbatim)
> [§Domain Hexagon] "DDD(도메인 주도 개발)의 그 Domain Layer로 기술에 독립적인 POJO로 개발"
> [§Application Hexagon] "Domain의 구성요소를 사용하여 시스템이 가지는 기능/사례(usecase)를 정의한 집합"
> [§Application Hexagon — 의존성] "의존성은 Domain Hexagon에 대해서만 가짐"
> [§Framework Hexagon] "Application hexagon이 소유한 outputPort (interface) 구현체들의 집합"
> [§Bootstrap Hexagon] "프로그램의 기능을 사용하기 위한 시작점"
> [§Port 통신] "Application Hexagon에 outputPort interface를 생성" / "Framework Hexagon에 outputPort의 구현체(adapter) 개발"
## Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| WW-HEX-C1 | 우아한형제들 헥사고날은 **4개 Hexagon 모듈 (Domain / Application / Framework / Bootstrap)** 으로 분리 | [§Domain Hexagon] "DDD(도메인 주도 개발)의 그 Domain Layer로 기술에 독립적인 POJO로 개발" + [§Application Hexagon] "Domain의 구성요소를 사용하여 시스템이 가지는 기능/사례(usecase)를 정의한 집합" + [§Framework Hexagon] "Application hexagon이 소유한 outputPort (interface) 구현체들의 집합" + [§Bootstrap Hexagon] "프로그램의 기능을 사용하기 위한 시작점" | `company-case-study` | 국내 대기업 헥사고날 multi-module 구성 사례 | 4-hexagon 구성이 모든 헥사고날 구현의 권장 표준이라는 뜻은 아님 — 우아한형제들의 한 사례 |
| WW-HEX-C2 | Application Hexagon 의 의존성은 **Domain Hexagon 에 대해서만** 존재 (framework 의존 0) | [§Application Hexagon — 의존성] "의존성은 Domain Hexagon에 대해서만 가짐" | `company-case-study` | 우아한형제들 헥사고날 모듈 의존성 규칙 | Gradle 빌드 단계에서 위반을 차단하는 구체적 메커니즘 (ArchUnit 등) 은 본 인용 범위 밖 |
| WW-HEX-C3 | port 통신 방식: **Application Hexagon 에 outputPort interface 생성 + Framework Hexagon 에 adapter 구현** | [§Port 통신] "Application Hexagon에 outputPort interface를 생성" / "Framework Hexagon에 outputPort의 구현체(adapter) 개발" | `company-case-study` | 우아한형제들 hexagonal port 위치 결정 | input port 의 위치 / use case 와 service 의 분리 정책은 본 인용 범위 밖 |
| WW-HEX-C4 | Domain Hexagon 은 **기술 독립적 POJO** 로 개발 — 프레임워크/인프라 의존 없음 | [§Domain Hexagon] "DDD(도메인 주도 개발)의 그 Domain Layer로 기술에 독립적인 POJO로 개발" | `company-case-study` | DDD + 헥사고날 domain 모듈 구성 | POJO 가 JPA `@Entity` 도 거부하는지 (= 순수 도메인 vs anemic) 는 본 인용에서 모호 |
| WW-HEX-C5 | 본 글은 transaction boundary / `@Transactional` 위치 / framework dependency 침투에 대해 **직접 다루지 않는다** (WebFetch 재확인: "@Transactional is NEVER mentioned anywhere in this article") | (부재 자체가 claim) | `needs-confirmation` | 본 글의 표현 범위 | 우아한형제들이 transaction boundary 정책을 어떻게 운영하는지에 대한 정보는 본 자료로 얻을 수 없음 — 다른 글 / 사내 자료 확인 필요 |
## Usage Boundaries / 적용 경계
- **이 자료가 직접 증명하는 것**:
- `WW-HEX-C1` ~ `C4`: 우아한형제들의 4-hexagon 모듈 구성, Application 의존 규칙, port 위치, Domain POJO 원칙
- `WW-HEX-C5`: 본 글이 transaction boundary 결정을 직접 다루지 않는다는 사실 (한국 백엔드 진영의 공통 공백)
- **이 자료가 증명하지 않는 것**:
- 우아한형제들의 transaction boundary 정책 (글에 부재)
- 4-hexagon 모듈 구성이 prod 환경에서 검증되었다는 측정값
- 모듈 분리만으로 트랜잭션 정책이 자동 해결된다는 주장
- 이 패턴이 한국 백엔드의 "공식 best practice" — `company-case-study` 사례일 뿐 (CLAUDE.md §5: company-tech-blog 는 사례/관점)
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
- ca-tmpl 의 single-module 구조 vs 4-hexagon multi-module 의 빌드 시간 / IDE 인덱싱 트레이드오프
- 우아한형제들의 다른 글 (예: "주니어 개발자의 클린 아키텍처 맛보기") 에서 transaction boundary 가 다뤄지는지
## 메모 / Notes (내 프로젝트 해석)
> 본 섹션은 자료 직접 인용 아님. ca-tmpl 결정 컨텍스트 해석.
- 적용 시나리오: 대규모 코드베이스에서 모듈 경계로 dependency rule 을 물리적으로 강제하고 싶을 때.
- 장점:
- Gradle multi-module 로 `application` 모듈이 `spring-tx` 의존을 아예 못 받게 만들 수 있다 → ca-tmpl 결정과 가장 호환적.
- 빌드 단계에서 위반 검출.
- 단점:
- 모듈 분리만으로는 트랜잭션 boundary 정책 자체가 정해지지 않음 → 결국 별도 port(=ca-tmpl 식) 또는 어댑터에서 wrap 결정이 필요.
- 모듈 수 늘면 빌드 시간/IDE 인덱싱 비용 증가.
- ca-tmpl(TransactionPort) 와의 차이: 우아한형제들 글은 **모듈 분리 인프라**, ca-tmpl 은 **모듈 분리 위에서의 트랜잭션 정책**. 둘은 보완 관계지 대안 관계가 아님. ca-tmpl 식 TransactionPort 는 이 모듈 구조 위에서 자연스럽게 안착한다.
- testability 영향: 모듈 분리 자체는 중립. 단 application 모듈을 spring-tx 의존에서 끊으면 ↑.
- code 복잡도 영향: 모듈 boilerplate 증가.
## 한계 / 확인 필요
- 본 글은 트랜잭션 관련 직접 문장이 없음. 우아한형제들의 트랜잭션 boundary 정책은 추가 다른 글 (예: "주니어 개발자의 클린 아키텍처 맛보기") 이나 사내 자료 확인 필요. → `status: needs-confirmation` 으로 후속 분류 후보 (이 raw 문서는 "공백 자체를 증거로" 기록한 `WW-HEX-C5`).
## Related / 관련
- 같은 주제 다른 raw:
- [[raw/company-tech-blogs/hexagonal-reflectoring-transactional-placement]] (baseline `@Transactional` direct)
- [[raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium]] (TransactionPort 대안)
- [[raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme]] (functional 통합 변형)
- 인용하는 branch:
- [[raw/branch-notes/feature-application-port-usecase-contract]]
- [[raw/branch-notes/feature-transaction-concurrency-contract]]
- 인용하는 project:
- [[raw/project-notes/ca-skeleton-operational-contract]] (§14, §5)
- 인용한 wiki 요약: (미작성)
- 대안 그룹: **Topic 2 — Transaction Boundary** (대안 5종: TransactionPort / @Transactional direct / TransactionTemplate / Functional monad / Custom AOP)
- 본 source 의 위치: 보완: multi-module 분리 (대체 X)