8.5 KiB
title, source_type, url, archive_url, status, confidence, tags, related_branches, related_projects, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | tags | related_branches | related_projects | created | last_reviewed | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Hexagonal Architecture with Java and Spring — Reflectoring (Tom Hombergs) | company-tech-blog | https://reflectoring.io/spring-hexagonal/ | raw | medium |
|
|
|
2026-05-22 | 2026-05-27 |
Hexagonal Architecture with Java and Spring — Tom Hombergs / Reflectoring
Layer:
raw/company-tech-blogs/— 외부 엔지니어 블로그의 원문 발췌·출처 기록. Tom Hombergs (저서 Get Your Hands Dirty on Clean Architecture 저자) 의 reflectoring.io 레퍼런스 글로, 헥사고날 사실상 표준 패턴에서@Transactional위치를 보여주는 baseline 사례. 검증된 요약은/ingest후wiki/concepts/에 별도 작성. 원본은 raw에 영구 보관.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-application-port-usecase-contract | ca-tmpl 이 의식적으로 거부한 baseline 패턴 (@Transactional 을 use case 구현체에 직접 부착) 의 사례 근거 |
| raw/branch-notes/feature-transaction-concurrency-contract | Topic 2 — Transaction Boundary 대안 비교에서 "대안 1: @Transactional direct" 의 reference 구현체 |
| raw/project-notes/ca-skeleton-operational-contract | §14. Transaction / Concurrency Contract — ca-tmpl 의 TransactionPort 결정에 대한 비교군 baseline |
컨텍스트 / 왜 저장했는지
ca-tmpl 결정의 비교군: 헥사고날 아키텍처 사실상 표준 reference 에서 @Transactional 을 application service(use case) 에 직접 부착하는 사례. 즉 ca-tmpl 이 의식적으로 거부한 baseline 패턴을 옹호하는 참조.
출처 / Source
- 원본 URL: https://reflectoring.io/spring-hexagonal/
- 아카이브 URL: (미수집)
- 저자 / 조직: Tom Hombergs (저서 Get Your Hands Dirty on Clean Architecture 저자) / reflectoring.io
- 발행일: continuously updated reference article
- 마지막 확인일: 2026-05-27
핵심 인용 / Key quotes (verbatim)
[§Building a Use Case and Output Ports] "
@RequiredArgsConstructor @Component @Transactional public class SendMoneyService implements SendMoneyUseCase {"
[§Input and Output Ports] "An input port is a simple interface that can be called by outward components and that is implemented by a use case."
[§Input and Output Ports] "An output port is again a simple interface that can be called by our use cases if they need something from the outside."
[§Input and Output Ports] "A use case in this sense is a class that handles everything around, well, a certain use case."
[§Building a Web Adapter] "If you're familiar with Spring MVC, you'll find that this is a pretty boring web controller."
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| HEX-REFL-C1 | reflectoring 레퍼런스 예제에서 SendMoneyService (use case 구현체) 가 @Component + @Transactional 을 직접 부착 |
[§Building a Use Case and Output Ports] "@RequiredArgsConstructor @Component @Transactional public class SendMoneyService implements SendMoneyUseCase {" |
engineering-blog |
Spring + 헥사고날 baseline 패턴 | 이 배치가 모든 헥사고날 구현의 모범이라는 뜻은 아님 — 저자도 명시적 정당화는 책으로 미룸 |
| HEX-REFL-C2 | input port 는 외부 컴포넌트가 호출하는 단순 인터페이스이고 use case 가 구현한다 | [§Input and Output Ports] "An input port is a simple interface that can be called by outward components and that is implemented by a use case." | engineering-blog |
헥사고날의 port 정의 (저자 관점) | port 의 granularity (큰 port 1개 vs use case 당 port 1개) 는 본 인용 범위 밖 |
| HEX-REFL-C3 | output port 는 use case 가 외부에 무언가 필요할 때 호출하는 단순 인터페이스 | [§Input and Output Ports] "An output port is again a simple interface that can be called by our use cases if they need something from the outside." | engineering-blog |
헥사고날의 driven-adapter 통신 방향 정의 | output port 가 트랜잭션 제어를 담당해야 한다는 뜻은 아님 — 본 글은 그 결정을 다루지 않음 |
| HEX-REFL-C4 | use case 는 "특정 use case 주변의 모든 것" 을 처리하는 클래스이다 | [§Input and Output Ports] "A use case in this sense is a class that handles everything around, well, a certain use case." | engineering-blog |
헥사고날 use case 의 책임 정의 | "모든 것" 의 정확한 경계 (트랜잭션, 인증, 검증 포함 여부) 는 본 인용에 명시 없음 |
| HEX-REFL-C5 | 본 글은 transaction boundary 정책 / @Transactional 부착 위치에 대한 명시적 권고 또는 정당화를 하지 않는다 (예제로만 보여줌) |
(부재 자체가 claim — WebFetch 재확인: "No explicit recommendation provided"; 본 인용 내에 transaction boundary 권고 문장 없음) | needs-confirmation |
본 글의 표현 범위 | 저자가 다른 매체 (책) 에서 다룬 정당화는 본 인용으로 증명 안 됨 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
HEX-REFL-C1: reflectoring 의 canonical 예제 코드 그대로의@Transactional위치 (use case 구현체 클래스)HEX-REFL-C2~C4: 저자의 port 와 use case 정의 (Hombergs 관점)HEX-REFL-C5: 본 글이 transaction boundary 결정의 정당화를 직접 제공하지 않는다는 사실
- 이 자료가 증명하지 않는 것:
- 이 패턴이 헥사고날 커뮤니티의 "공식 best practice" 라는 주장 (
company-tech-blog수준이 아니라engineering-blog수준 — 개인 블로그) - 이 패턴이 prod 환경에서 검증되었다는 주장 (저자의 책/블로그 reference 예제일 뿐)
- "framework-free 원칙 위반" 이라는 비판 — 본 글이 직접 그 표현을 쓰지 않음
- 이 패턴이 헥사고날 커뮤니티의 "공식 best practice" 라는 주장 (
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-tmpl 의 TransactionPort 가 reflectoring 패턴 대비 갖는 dependency rule 차이 (Spring annotation import 유무) 의 실제 측정
- 저자의 책 Get Your Hands Dirty on Clean Architecture 에서 동일 결정의 정당화 본문 확인
메모 / Notes (내 프로젝트 해석)
본 섹션은 자료 직접 인용 아님. ca-tmpl 결정 컨텍스트 해석.
- 이 패턴이 한국·해외 헥사고날 튜토리얼의 90% 이상에서 그대로 반복됨. ca-tmpl 의 결정은 이 디폴트에 대한 의식적 일탈로 봐야 함.
- 적용 시나리오: 빠른 프로토타이핑, 팀이 Spring 이외 stack 으로 옮길 계획이 없는 경우.
- 장점:
- 코드 적음. 진입 장벽 최저.
- 헥사고날 커뮤니티 표준이라 코드 리뷰/온보딩 용이.
- 단점:
- application 레이어가
org.springframework.transaction.annotation.Transactional을 import → 책에서 강조하는 "domain-application 은 framework-free" 원칙과 실제 코드가 어긋남. (저자도 명시적 정당화 없음 —HEX-REFL-C5참조.) - 트랜잭션 boundary 테스트가 Spring context 를 요구.
- application 레이어가
- ca-tmpl(TransactionPort) 와의 차이: ca-tmpl 은 위 모순을 닫기 위해
TransactionPort+TransactionalUseCaseRunner로 한 단계 더 abstraction 을 둠. Reflectoring 패턴은 그 모순을 실용주의로 수용. - testability 영향: 낮음.
- code 복잡도 영향: 낮음 (하지만 dependency-rule cost 는 숨겨져 있음).
Related / 관련
- 같은 주제 다른 raw:
- raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium (TransactionPort 도입 사례)
- raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme (TransactionInterceptor 확장)
- raw/company-tech-blogs/woowahan-hexagonal-multimodule (multi-module 보완)
- 인용하는 branch:
- 인용하는 project:
- 인용한 wiki 요약: (미작성)
- 대안 그룹: Topic 2 — Transaction Boundary (대안 5종: TransactionPort / @Transactional direct / TransactionTemplate / Functional monad / Custom AOP)
- 본 source 의 위치: 대안 1: @Transactional direct (Hexagonal 변형)