Files
llm-wiki/raw/company-tech-blogs/hexagonal-reflectoring-transactional-placement.md

106 lines
8.5 KiB
Markdown

---
title: "Hexagonal Architecture with Java and Spring — Reflectoring (Tom Hombergs)"
source_type: company-tech-blog
url: https://reflectoring.io/spring-hexagonal/
archive_url:
status: raw
confidence: medium
tags: [ca-transaction-boundary, hexagonal, at-transactional, application-service]
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
---
# 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 원칙 위반" 이라는 비판 — 본 글이 직접 그 표현을 쓰지 않음
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
- 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 를 요구.
- 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:
- [[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 의 위치: 대안 1: @Transactional direct (Hexagonal 변형)