Files
llm-wiki/raw/company-tech-blogs/arhohuttunen-hexagonal-architecture-spring-boot.md

7.6 KiB
Raw Permalink Blame History

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
company-tech-blog / Hexagonal Architecture With Spring Boot — Arho Huttunen company-tech-blog https://www.arhohuttunen.com/hexagonal-architecture-spring-boot/
feature-persistence-auditing-contract
ca-tmpl
company-tech-blog
ca-tmpl
architecture
spring-boot
hexagonal
clean-architecture
domain-purity
2026-06-10

company-tech-blog / Hexagonal Architecture With Spring Boot — Arho Huttunen

Layer: raw/ — 외부 자료(전문가 기술 블로그)의 원문 발췌·출처 기록. 검증된 요약은 /ingestwiki/concepts/source-summary-template 형식으로 별도 작성. 원본은 raw에 영구 보관.

Parent / 활용 branch (필수)

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-persistence-auditing-contract D2 (core mandate): Hexagonal / Clean Architecture 에서 JPA Entity 및 persistence 관심사는 persistence adapter 안에만 존재하고 domain model 과 분리해야 한다 — 따라서 audit 메타데이터(created_at / updated_at / created_by / updated_by)는 persistence-adapter JPA entity 또는 @MappedSuperclass 에 속하며, domain-core aggregate 를 오염시켜서는 안 된다.

출처 / Source

왜 저장했는지 / Why archived

Hexagonal Architecture 에서 JPA Entity 를 domain model 과 분리해야 한다는 구체적 설계 패턴과 근거를 담고 있다. 특히 OrderEntity (JPA) vs Order (domain) 분리 패턴 및 persistence adapter 가 두 모델 사이의 mapping 을 전담한다는 내용은 feature-persistence-auditing-contract 의 D2 결정 — audit 메타데이터를 JPA entity 에만 두고 domain aggregate 를 오염시키지 않는다 — 을 직접 정당화한다.

핵심 인용 / Key quotes (verbatim, 3~5문장)

[§Persistence Adapter / Secondary Adapters] "The OrderEntity itself holds the jakarta.persistence annotations for ORM."

[§Persistence Adapter / Secondary Adapters] "A lot of applications pollute the domain model with such annotations. Here we have a clean separation of those concerns with the cost of having to do mapping between the models."

[§Persistence Adapter / Secondary Adapters] "The OrdersJpaAdapter takes care of the translation between the domain and the JPA entities."

[§Module Structure / Application Module] "the coffeeshop-application holds all the business logic and use cases of the application and does not depend on Spring Boot at all. In fact, the only dependencies it has are JUnit 5 and AssertJ."

[§Transaction Management] "if we truly want to keep frameworks out of the application core, we can do better."

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
C1 JPA (jakarta.persistence) annotation 은 JPA entity class 에만 달고, domain model class 에는 달지 않는 것이 hexagonal architecture 의 관심사 분리 방식이다 [§Secondary Adapters] "The OrderEntity itself holds the jakarta.persistence annotations for ORM." engineering-blog Spring Boot + JPA 기반 Hexagonal Architecture JPA 이외의 persistence 기술(MongoDB, R2DBC 등)에서의 적용 방식 / Spring Data JPA 의 공식 권고 사항
C2 Domain model 에 JPA annotation 을 추가하는 것은 관심사 오염이며, 올바른 분리는 domain ↔ JPA entity 매핑 비용을 수반한다 [§Secondary Adapters] "A lot of applications pollute the domain model with such annotations. Here we have a clean separation of those concerns with the cost of having to do mapping between the models." engineering-blog persistence 관심사를 domain model 과 분리하려는 모든 아키텍처 매핑 비용의 구체적 수치 / 도메인 오염이 실제 프로젝트에서 야기하는 장애
C3 Persistence adapter 가 domain 객체와 JPA entity 사이의 변환(translation)을 전담한다 [§Secondary Adapters] "The OrdersJpaAdapter takes care of the translation between the domain and the JPA entities." engineering-blog Hexagonal Architecture 의 secondary adapter 구현 MapStruct 등 특정 매핑 라이브러리의 사용 필수 여부 / 성능 특성
C4 Application (domain) 모듈은 Spring Boot 에 전혀 의존하지 않는 것이 가능하다 — 테스트 라이브러리 외 프레임워크 의존성 zero [§Module Structure] "the coffeeshop-application holds all the business logic and use cases of the application and does not depend on Spring Boot at all. In fact, the only dependencies it has are JUnit 5 and AssertJ." engineering-blog Gradle multi-module 기반 Hexagonal Architecture 모든 Spring Boot 프로젝트에서 이 모듈 분리가 강제된다는 것 / 성능·빌드 시간 영향
C5 @Transactional 과 같은 Spring 프레임워크 annotation 을 domain core 에 두는 것은 프레임워크 오염이며, 더 나은 방법(AOP aspect 활용 등)이 존재한다 [§Transaction Management] "if we truly want to keep frameworks out of the application core, we can do better." engineering-blog Spring @Transactional 을 domain use case 에서 제거하고자 하는 설계 Spring AOP aspect 방식이 모든 트랜잭션 경계 시나리오에서 동일하게 동작한다는 보장

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • C1C3: Spring Boot + JPA 조합에서 JPA entity 와 domain model 을 분리하고 adapter 가 매핑을 담당하는 구체적 구현 패턴 (저자의 예제 코드 기반)
    • C4: Gradle multi-module 분리로 application module 의 Spring Boot 무의존성이 달성 가능함
    • C5: @Transactional 을 domain core 밖으로 이동하는 방향성
  • 이 자료가 증명하지 않는 것:
    • 이 패턴이 Spring 공식 권고 또는 best practice 임을 증명하지 않는다 (개인 블로그 — engineering-blog 등급)
    • audit 메타데이터(created_at, updated_by 등)를 JPA entity 에 두어야 한다는 것을 직접 언급하지 않는다 (D2 결론은 C1–C3 를 도메인에 적용한 추론)
    • @MappedSuperclass 또는 Spring Data JPA @EnableJpaAuditing 의 구체적 설정
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • ca-tmpl 에서 audit entity (AuditableEntity 또는 BaseEntity) 가 실제로 JPA layer 에만 존재하는지 코드 grep 으로 검증 필요
    • domain aggregate(Order, Member 등)에 JPA annotation 이 없는지 ArchUnit rule 으로 강제 여부 확인

메모 / Notes

  • 이 블로그는 저자(Arho Huttunen)의 개인 전문가 블로그로, 대기업 엔지니어링 블로그가 아니다. 사용자가 company-tech-blog로 지정했으나, claim strength 는 engineering-blog 로 분류했다 — company-case-study 보다 낮은 등급.
  • 기술 블로그 단독으로는 "공식 best practice"로 인용 불가. D2 결정의 근거로 쓰되, Spring Data JPA 공식 문서(official-vendor-doc 등급)와 함께 병기하는 것이 권고됨.
  • 저자가 제공하는 전체 예제 코드는 Codeberg 에 있다고 언급됨 (링크 미포함).