17 KiB
title, source_type, url, related_branches, related_projects, tags, status, confidence, created
| title | source_type | url | related_branches | related_projects | tags | status | confidence | created | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| personal-blog / Buckpal — ArchUnit Lombok allowlist + direct @Transactional (CONTRARY EVIDENCE to ca-tmpl D3/D1) | personal-blog | https://github.com/thombergs/buckpal |
|
|
|
raw | medium | 2026-05-28 |
personal-blog / Buckpal — ArchUnit Lombok allowlist + direct @Transactional (CONTRARY EVIDENCE to ca-tmpl D3/D1)
Layer:
raw/company-tech-blogs/— 외부 자료(개인 블로그·책 공식 예제 코드) 원문 발췌·출처 기록. CONTRARY EVIDENCE 노트: ca-tmpl 의 결정 D3 (domain-core Lombok 금지) 와 D1 (@Transactional 직접 import 금지) 과 반대 방향인 OSS 선례를 기록한다. 이 자료는 ca-tmpl 결정을 reject 하기 위한 것이 아니라, ca-tmpl 이 "OSS 다수파 best practice" 가 아닌 ca-tmpl 자체 stricter stance 임을 솔직히 명시하기 위한 근거다.
Parent / 활용 branch (필수, 최소 1개+)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-architecture-enforcement-rules | D3 CONTRARY evidence — Buckpal domain purity ArchUnit rule 이 lombok.. 패키지를 명시적으로 allowlist 함으로써, "domain-core Lombok 금지" 가 OSS 공통 표준이 아니라 ca-tmpl 자체 stricter stance 임을 뒷받침 |
| raw/branch-notes/feature-application-port-usecase-contract | D1 CONTRARY evidence — Buckpal application service 가 @Transactional 을 직접 클래스에 부착함으로써, "Spring @Transactional 직접 import 금지" 가 OSS 다수파가 아닌 ca-tmpl 소수파 결정임을 뒷받침 |
출처 / Source
- 원본 URL (repo): https://github.com/thombergs/buckpal
- DependencyRuleTests.java: https://raw.githubusercontent.com/thombergs/buckpal/master/src/test/java/io/reflectoring/buckpal/DependencyRuleTests.java
- SendMoneyService.java: https://raw.githubusercontent.com/thombergs/buckpal/master/src/main/java/io/reflectoring/buckpal/application/domain/service/SendMoneyService.java
- UseCase.java: https://raw.githubusercontent.com/thombergs/buckpal/master/src/main/java/io/reflectoring/buckpal/common/UseCase.java
- 아카이브 URL: (미등록 — GitHub raw 직접 링크)
- 저자: Tom Hombergs (Reflectoring.io, "Get Your Hands Dirty on Clean Architecture" 저자)
- 자료 성격: 개인 블로그(reflectoring.io) + 책("Get Your Hands Dirty on Clean Architecture") 공식 예제 코드
- repo star: ≥2,500 (2026-05-28 확인 시점 기준, Hexagonal Architecture Java OSS 중 가장 영향력 있는 reference)
- single-module 여부: repo root 에
build.gradle1개,settings.gradle부재 → 단일 Gradle 모듈 확인 (GitHub API tree 검증) - 마지막 확인일: 2026-05-28
왜 저장했는지 / Why archived
Buckpal 은 Hexagonal Architecture Java 구현의 사실상 가장 영향력 있는 OSS 예제다. 그런데 ca-tmpl 의 두 핵심 결정 — (1) domain-core 에서 Lombok annotation 금지, (2) application layer 에서 Spring @Transactional 직접 import 금지 — 과 정반대 방향을 택하고 있다. ca-tmpl 결정 문서에서 "우리가 OSS 다수파와 다르다" 는 사실을 솔직히 기록하기 위해 보관한다. 이 자료가 ca-tmpl 결정을 부정하는 것이 아니라, 결정이 "stricter / 소수파" 임을 명시하는 CONTRARY evidence 로 기능한다.
핵심 인용 / Key quotes (verbatim, self-grep 통과)
[DependencyRuleTests.java §domainModelDoesNotDependOnOutside] "void domainModelDoesNotDependOnOutside() { noClasses() .that() .resideInAPackage("io.reflectoring.buckpal.application.domain.model..") .should() .dependOnClassesThat() .resideOutsideOfPackages( "io.reflectoring.buckpal.application.domain.model..", "lombok..", "java.." ) .check(new ClassFileImporter() .importPackages("io.reflectoring.buckpal..")); }"
— Source: DependencyRuleTests.java line 33–46. domain model 이 의존할 수 있는 외부 패키지를
lombok..와java..로 명시적 allowlist 함.
[DependencyRuleTests.java §import] "import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;"
— Source: DependencyRuleTests.java line 7. ArchUnit
noClasses()DSL 직접 사용 확인.
[SendMoneyService.java §class-declaration] "@RequiredArgsConstructor @UseCase @Transactional public class SendMoneyService implements SendMoneyUseCase {"
— Source: SendMoneyService.java line 16–19. application service 에
@UseCase(=@Componentmeta-annotation) +@Transactional직접 클래스 레벨 부착. Spring DI + transaction boundary 를 추상화 없이 직접 선언.
[SendMoneyService.java §import] "import jakarta.transaction.Transactional;"
— Source: SendMoneyService.java line 13.
jakarta.transaction.Transactional직접 import.org.springframework.transaction.annotation.Transactional이 아닌 Jakarta EE 표준 어노테이션 사용 (Spring 은 양쪽 모두 지원).
[UseCase.java §meta-annotation] "@Component public @interface UseCase { @AliasFor(annotation = Component.class) String value() default ""; }"
— Source: UseCase.java line 14–19 (핵심 부분).
@UseCase는@Component의 meta-annotation. 즉 SendMoneyService 는 사실상@Component @Transactional직접 부착.
Claims Extracted / 추출된 주장
이 자료가 직접 말하는 것만 claim 으로 분리한다. ca-tmpl 에 적용한 해석은 여기 쓰지 않는다.
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| BUCKPAL-LOMBOK-C1 | Buckpal domain purity ArchUnit rule 은 domain model 이 lombok.. 패키지에 의존하는 것을 허용 (resideOutsideOfPackages allowlist 에 "lombok.." 포함) |
[DependencyRuleTests.java §domainModelDoesNotDependOnOutside] "lombok.." (line 41 of fetched file) |
engineering-blog (개인 블로그 + 책 예제 — Spring/ArchUnit 공식 아님) |
Java Hexagonal Architecture 에서 domain-core 가 Lombok 에 의존하는 것이 기술적으로 가능하며 저명한 예제에서 채택됨을 보여주는 선례 | Lombok 사용이 "옳다" 또는 "권장된다" 는 것. 단지 "Buckpal 은 그렇게 결정했다" 만 증명. ca-tmpl 의 금지 결정을 부정하지 않음 |
| BUCKPAL-LOMBOK-C2 | domain model 이 Lombok annotation 을 사용해도 domain purity ArchUnit rule 을 통과하도록 설계 가능하다 (rule 자체가 Lombok 을 외부 침해로 간주하지 않음) | [DependencyRuleTests.java §domainModelDoesNotDependOnOutside] "lombok.." 가 resideOutsideOfPackages 의 허용 목록에 포함됨 (line 41) |
engineering-blog |
Buckpal 설계 기준에서 Lombok = domain 내부 허용 도구. 이 선택이 책 시장에서 ≥2.5k star OSS 예제로 수용된 사실 | Lombok 이 "domain purity 에 영향을 주지 않는다" 는 일반 원칙. Buckpal 이 Lombok 사용의 장단점을 공식 분석했음을 증명하지 않음 |
| BUCKPAL-TX-C1 | Buckpal SendMoneyService 는 @Transactional 어노테이션을 클래스 레벨에 직접 부착하여 transaction boundary 를 선언 |
[SendMoneyService.java §class-declaration] "@UseCase @Transactional public class SendMoneyService implements SendMoneyUseCase {" (line 16–19) |
engineering-blog |
Hexagonal Architecture Java 에서 application service 가 Spring/Jakarta @Transactional 직접 선언하는 패턴의 저명한 구현 선례 |
@Transactional 직접 부착이 "Hexagonal Architecture 의 표준" 이거나 "best practice" 임. 단지 "Buckpal 은 그렇게 구현했다" 만 증명 |
| BUCKPAL-TX-C2 | Buckpal 에는 TransactionPort / TransactionRunner / UnitOfWork 같은 transaction abstraction 이 존재하지 않음 — Spring @Transactional 직접 사용 |
[SendMoneyService.java §import] "import jakarta.transaction.Transactional;" (line 13) + class declaration (line 16–19). 별도 transaction port interface 파일 부재 (GitHub API tree 검증) |
engineering-blog |
Buckpal 설계에서 transaction abstraction layer 는 선택이 아닌 생략. 이 생략이 책 예제로 수용된 사실 | transaction abstraction 이 불필요하다는 일반 원칙. ca-tmpl 의 TransactionPort 결정이 잘못됐음을 증명하지 않음 |
Strength 허용값 참고
- 본 자료의 모든 claim:
engineering-blog— Tom Hombergs 개인 블로그 + 책 예제. Spring 공식/ArchUnit 공식 아님. company-case-study로 분류하지 않은 이유: Buckpal 은 기업 엔지니어링 블로그 출처가 아닌 개인 저자(Tom Hombergs)의 책 예제.
Usage Boundaries / 적용 경계
이 자료가 직접 증명하는 것
BUCKPAL-LOMBOK-C1: Buckpal 이 domain purity rule 에서lombok..를 명시적으로 allowlist 한다는 코드 사실BUCKPAL-LOMBOK-C2: domain-core + Lombok 공존 설계가 저명한 OSS 예제에서 실제로 구현됨BUCKPAL-TX-C1: Buckpal 이@Transactional을 application service 클래스 레벨에 직접 부착함BUCKPAL-TX-C2: Buckpal 에 transaction abstraction 계층이 없음
이 자료가 증명하지 않는 것
- Lombok 사용이 domain purity 원칙과 양립 가능하다는 일반 원칙 (단지 Buckpal 의 구현 결정)
@Transactional직접 부착이 Hexagonal Architecture 의 "공식" 또는 "권장" 방식 (Spring 공식 문서는@Transactional지원을 명시하지만 Hexagonal Architecture 특정 배치 지침은 제공하지 않음)- ca-tmpl 의 D3 (Lombok 금지) 또는 D1 (
@Transactional금지) 결정이 잘못됐음 - Buckpal 패턴이 다른 프로젝트에 직접 이식 가능함 (Buckpal 은 single-module, ca-tmpl 은 multi-module)
ca-tmpl 에 적용하려면 추가 확인이 필요한 것
- 이 자료는 CONTRARY evidence 로만 사용한다. ca-tmpl 결정 D3/D1 을 변경하려면 별도 Decision Review 필요
- Buckpal 의 single-module 구조 vs ca-tmpl 의 multi-module Gradle 구조 차이 — module boundary 가 강한 격리를 제공하는 multi-module 환경에서 Lombok classpath 포함 여부는 별도 평가 필요
메모 / Notes
- Buckpal 은 단일 Gradle 모듈 (
build.gradle1개,settings.gradle부재). ca-tmpl 과 module 구조가 근본적으로 다름. domain purity rule 의 의미가 다를 수 있음. - Buckpal 의
@Transactional은jakarta.transaction.Transactional(Jakarta EE 표준). ca-tmpl 금지 대상인org.springframework.transaction.annotation.Transactional과 다른 import path — 하지만 Spring 은 양쪽 모두 처리하고, ca-tmpl ArchUnit rule 은jakarta.transaction.Transactional도 별도 금지 검토 대상으로 볼 수 있음. 이 세부 사항은feature-architecture-enforcement-rulesbranch 에서 확인 필요. @UseCase는@Componentmeta-annotation (UseCase.java 원문 확인). 즉 SendMoneyService 에서@UseCase @Transactional=@Component @Transactional. ca-tmpl 은@Component/@Service를 application-core 에서 허용(D13)하고@Transactional만 금지. 이 분리는 Buckpal 과 다름.- 추가로 봐야 할 Buckpal 관련 자료: raw/company-tech-blogs/hexagonal-reflectoring-transactional-placement — 이미 보관된 Hombergs 블로그 글이
@Transactional배치를 직접 다룸. BUCKPAL-TX-C1/C2 와 함께 읽으면 Hombergs 의 입장이 더 명확해짐.
Decision Evidence Map / 결정-근거 매핑
이 raw source 가 각 parent branch 의 어떤 Decision ID 를 뒷받침(또는 반박)하는지 명시한다.
CONTRARY= 결정과 반대 방향의 evidence (결정 자체를 reject 하지 않음 — 결정이 소수파임을 기록).UNSUPPORTED_DECISION= 이 자료만으로는 증명 불충분.
Parent: feature-architecture-enforcement-rules
| Decision ID | Decision (요약) | This source's role | Supporting Claim IDs | Evidence Strength | Notes |
|---|---|---|---|---|---|
| D3 | domain-core forbidden import rule (Lombok 포함) |
CONTRARY — Buckpal 은 domain purity rule 에서 lombok.. 를 allowlist. ca-tmpl 금지 결정과 반대 방향 |
BUCKPAL-LOMBOK-C1, BUCKPAL-LOMBOK-C2 |
engineering-blog |
D3 결정 자체를 override 하지 않음. "ca-tmpl D3 가 OSS 공통 표준이 아닌 자체 stricter stance" 임을 입증하는 CONTRARY evidence 로만 사용 |
| D8 | application @Transactional 직접 import 금지 |
CONTRARY (보조) — Buckpal application service 가 @Transactional 직접 부착. feature-architecture-enforcement-rules D8 이 feature-application-port-usecase-contract 를 근거로 인용하므로 간접 CONTRARY |
BUCKPAL-TX-C1, BUCKPAL-TX-C2 |
engineering-blog |
D8 원 근거는 feature-application-port-usecase-contract. 본 자료는 보조 CONTRARY evidence. D8 결정을 override 하지 않음 |
| D1, D2, D4 |
기타 결정 | NOT APPLICABLE — 이 자료는 ArchUnit DSL 사용 사실(Q3), domain purity allowlist(Q1/Q2) 만 증명. 나머지 결정(Gradle module boundary, shared-contract scope, sample-ticket 금지, ArchUnit fail mode 등)에 대한 직접 claim 없음 | — | — | UNSUPPORTED_DECISION 아님 — 이 자료의 범위 밖 결정들. 기존 cited sources 가 별도로 지원 |
Parent: feature-application-port-usecase-contract
| Decision ID | Decision (요약) | This source's role | Supporting Claim IDs | Evidence Strength | Notes |
|---|---|---|---|---|---|
| D3 | application use case 가 transaction boundary owner — but Spring @Transactional 직접 import 금지, TransactionPort 사용 |
CONTRARY — Buckpal 은 TransactionPort abstraction 없이 @Transactional 직접 부착. 이 자료는 "다수파" 가 어떻게 구현하는지를 구체적 OSS 코드로 뒷받침 |
BUCKPAL-TX-C1, BUCKPAL-TX-C2 |
engineering-blog |
D3 자체는 UNIL-TX-C1/C2, VSOUM-TX-C1/C2 로 지원됨 (company-case-study). 이 자료는 그 결정이 소수파임을 보강하는 CONTRARY evidence. D3 를 UNSUPPORTED_DECISION 으로 격하하지 않음 |
| D4 | @Transactional 직접 부착이 hexagonal 표준 다수파임을 인정 |
SUPPORTING (CONTRARY direction) — D4 는 ca-tmpl 이 이미 인정한 "다수파" 사실. 이 자료의 BUCKPAL-TX-C1/C2 는 그 다수파의 구체적 저명 OSS 선례를 제공 | BUCKPAL-TX-C1, BUCKPAL-TX-C2 |
engineering-blog |
D4 는 이미 AT-TX-C1, HEX-REFL-C1/C5 로 지원됨. 이 자료는 추가 corroborating evidence |
| D1, D2, D5~D14 | 기타 결정 | NOT APPLICABLE — 이 자료는 Buckpal 의 @Transactional 직접 사용 패턴만 증명. naming convention, CQS 분리, TransactionTemplate, Arrow Kt, AOP interceptor, pool sizing, KEYED freeze 등에 대한 직접 claim 없음 |
— | — | UNSUPPORTED_DECISION 아님 — 이 자료의 범위 밖 결정들 |
UNSUPPORTED_DECISION 목록 (이 자료 기준)
이 raw source 단독으로 아래 진술을 지지하면 UNSUPPORTED_DECISION:
| 진술 | 판정 | 이유 |
|---|---|---|
| "Lombok 사용이 domain purity 에 문제없다" | UNSUPPORTED_DECISION | BUCKPAL-LOMBOK-C1/C2 는 Buckpal 의 설계 결정만 증명. 일반 원칙으로 확대 불가 |
"@Transactional 직접 부착이 Hexagonal Architecture 의 권장 패턴이다" |
UNSUPPORTED_DECISION | BUCKPAL-TX-C1/C2 는 Buckpal 선례만 증명. Spring 공식 또는 Hexagonal Architecture 명세가 이 배치를 "권장" 한다고 말하지 않음 |
| "ca-tmpl D3 (Lombok 금지) 결정이 잘못됐다" | UNSUPPORTED_DECISION | 이 자료는 CONTRARY evidence. override 의도 아님. D3 변경은 별도 Decision Review 필요 |
| "ca-tmpl D3 (TransactionPort) 결정이 잘못됐다" | UNSUPPORTED_DECISION | 동일 — CONTRARY evidence. UNIL-TX-C1/C2, VSOUM-TX-C1/C2 가 TransactionPort 선택 근거로 별도 지원됨 |
Related / 관련
- raw/company-tech-blogs/hexagonal-reflectoring-transactional-placement — 동일 저자(Tom Hombergs)의
@Transactional위치에 관한 블로그 글. BUCKPAL-TX-C1 의 맥락 보완 - raw/official-docs/at-transactional-spring-official —
@Transactional직접 부착의 Spring 공식 지원 근거. BUCKPAL-TX-C1 와 함께 "다수파" 를 구성하는 공식 근거 - raw/official-docs/lombok-builder-data-features-official — ca-tmpl D3 의 Lombok 금지 근거. BUCKPAL-LOMBOK-C1 의 반대 방향 공식 문서
- raw/branch-notes/feature-architecture-enforcement-rules — D3 결정 원문. BUCKPAL-LOMBOK-C1/C2 가 CONTRARY evidence 로 기재되어야 하는 Decision Evidence Map 위치
- raw/branch-notes/feature-application-port-usecase-contract — D1/D3/D4 결정 원문. BUCKPAL-TX-C1/C2 가 CONTRARY evidence 로 기재되어야 하는 Decision Evidence Map 위치