Files
llm-wiki/raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md
T

17 KiB
Raw Blame History

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
feature-architecture-enforcement-rules
feature-application-port-usecase-contract
ca-skeleton
personal-blog
ca-skeleton
architecture
archunit
lombok
transaction
hexagonal
domain-purity
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


왜 저장했는지 / 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 3346. 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 1619. application service 에 @UseCase (= @Component meta-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 1419 (핵심 부분). @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 1619) 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 1619). 별도 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.gradle 1개, settings.gradle 부재). ca-tmpl 과 module 구조가 근본적으로 다름. domain purity rule 의 의미가 다를 수 있음.
  • Buckpal 의 @Transactionaljakarta.transaction.Transactional (Jakarta EE 표준). ca-tmpl 금지 대상인 org.springframework.transaction.annotation.Transactional 과 다른 import path — 하지만 Spring 은 양쪽 모두 처리하고, ca-tmpl ArchUnit rule 은 jakarta.transaction.Transactional 도 별도 금지 검토 대상으로 볼 수 있음. 이 세부 사항은 feature-architecture-enforcement-rules branch 에서 확인 필요.
  • @UseCase@Component meta-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, D4D7, D9D12 기타 결정 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 선택 근거로 별도 지원됨