Reviewed technical note
Spring/JPA에서 도메인 모델 경계가 무너지는 순간
도메인 모델 패턴, 헥사고날 아키텍처, JPA 성능 지식을 블로그 글로 연결하기 위한 첫 기준.
Spring/JPA 애플리케이션에서 도메인 모델은 처음에는 깨끗하다. 문제는 시간이 지나며 컨트롤러, 서비스, 엔티티, 조회 최적화 코드가 서로의 책임을 침범할 때 시작된다.
경계가 무너지는 대표 신호
- 엔티티가 API 응답 형식을 직접 의식한다.
- 서비스가 트랜잭션 스크립트처럼 모든 규칙을 순서대로 나열한다.
- 조회 성능 문제를 해결하려고 도메인 규칙이 리포지토리 쿼리로 이동한다.
- 테스트가 도메인 규칙이 아니라 컨트롤러 응답 모양에만 붙는다.
- JPA 지연 로딩, fetch join, OSIV 같은 인프라 선택이 도메인 설계를 끌고 간다.
이 상태에서는 기능은 동작해도 변경이 어려워진다. 새 정책 하나를 추가하기 위해 API 계층, 서비스 계층, 영속성 계층을 동시에 만져야 한다.
도메인 모델과 JPA는 분리해서 생각해야 한다
JPA 엔티티는 도메인 모델을 담을 수 있지만, JPA 자체가 도메인 모델을 만들어주지는 않는다. 도메인 규칙은 언어와 메서드, 불변식으로 표현해야 한다. 영속성 최적화는 그 다음 문제다.
헥사고날 아키텍처가 유용한 이유도 여기에 있다. 포트와 어댑터를 나누면 웹 API, DB, 외부 시스템이 도메인 규칙의 중심으로 들어오는 일을 막을 수 있다.
성능 최적화는 경계 밖에서 시작한다
JPA 성능 문제는 중요하다. 하지만 성능 최적화를 도메인 규칙 안에 섞으면 장기적으로 더 비싼 문제가 된다. 조회 모델, fetch join, batch size, projection은 대부분 읽기 경로의 선택이다. 쓰기 모델의 불변식과 분리해서 다뤄야 한다.
블로그 자동 운영 관점에서는 이 주제가 좋은 시리즈가 된다.
- 도메인 모델이 이끄는 개발
- 헥사고날 아키텍처와 포트
- JPA 조회 성능과 fetch join
- OSIV와 트랜잭션 경계
- 아키텍처 테스트로 경계 지키기
위키에 이미 Spring/JPA와 아키텍처 자료가 충분하므로, 각 글은 단순 요약이 아니라 “경계가 깨지는 구체적 증상과 복구 방법” 중심으로 작성하는 편이 좋다.