Files
llm-wiki/raw/official-docs/domain-fowler-anemic-vs-rich-model.md

10 KiB

title, source_type, url, archive_url, status, confidence, tags, related_branches, related_projects, created, last_reviewed
title source_type url archive_url status confidence tags related_branches related_projects created last_reviewed
Martin Fowler — Anemic Domain Model (anti-pattern) official-doc https://martinfowler.com/bliki/AnemicDomainModel.html https://web.archive.org/web/2024/https://martinfowler.com/bliki/AnemicDomainModel.html raw high
domain
ddd
anemic-model
rich-model
fowler
ca-skeleton
feature-domain-modeling-guardrails
feature-architecture-enforcement-rules
feature-skeleton-package-blueprint-contract
feature-domain-feature-onboarding-contract
ca-skeleton-operational-contract
2026-05-22 2026-05-27

Martin Fowler — AnemicDomainModel

Layer: raw/official-docs/ — Martin Fowler bliki "AnemicDomainModel" (2003-11-25) verbatim 발췌. ca-tmpl 의 Rich Domain Model 강제 결정 (invariant in constructor / safe reason enum / domain logger ban) 의 1차 근거.

Parent / 활용 branch (필수)

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-domain-modeling-guardrails rich model 강제 — domain class에 invariant 위치, mutation은 aggregate method 호출만, anemic getter/setter 거부
raw/branch-notes/feature-architecture-enforcement-rules "all logic in *Service" anemic 패턴을 ArchUnit 룰로 차단 (domain method 비어있으면 lint 경고) 근거
raw/branch-notes/feature-skeleton-package-blueprint-contract feature 패키지 내 domain/ 디렉터리가 단순 DTO 가 아니라 behavior 포함 entity/VO 임을 강제
raw/branch-notes/feature-domain-feature-onboarding-contract 신규 feature 온보딩 시 anemic 회피 체크리스트 (생성 시 invariant validation / setter 노출 금지) 근거

컨텍스트 / 왜 저장했는지

ca-tmpl 결정: "domain logger ban + safe reason enum + invariant in constructor"는 Rich Domain Model을 강제하는 결정. 반대 방향(Anemic Model)은 ca-tmpl이 명시적으로 거부한 안티패턴. Fowler의 글이 가장 자주 인용되는 출처.

출처 / Source

핵심 인용 / Key quotes (verbatim)

[§Opening] "at first blush it looks like the real thing...little more than bags of getters and setters"

[§Critique] "The fundamental horror of this anti-pattern is that it's so contrary to the basic idea of object-oriented design; which is to combine data and process together."

[§Critique] "The anemic domain model is really just a procedural style design, exactly the kind of thing that object bigots like me...have been fighting"

[§Cost] "they incur all of the costs of a domain model, without yielding any of the benefits"

[§Cost] "The primary cost is the awkwardness of mapping to a database, which typically results in a whole layer of O/R mapping"

[§Consequence] "you essentially end up with Transaction Scripts, and thus lose the advantages that the domain model can bring"

[§Domain logic] "The logic that should be in a domain object is domain logic - validations, calculations, business rules"

[§Eric Evans 인용] "the more common mistake is to give up too easily on fitting the behavior into an appropriate object, gradually slipping toward procedural programming."

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
FOWLER-ANEMIC-C1 Anemic Domain Model 은 OO 의 핵심 원칙 (data + process 결합) 에 반하므로 anti-pattern 으로 분류된다 [§Critique] "it's so contrary to the basic idea of object-oriented design; which is to combine data and process together" engineering-blog OO 언어 (Java/C#/Smalltalk 류) 도메인 모델 모든 getter/setter heavy 클래스가 anemic 이라는 뜻은 아님 — Transaction Script 패턴 자체는 별도 trade-off 결정
FOWLER-ANEMIC-C2 Anemic model 은 절차적 (procedural) 스타일 설계와 동등하다 [§Critique] "The anemic domain model is really just a procedural style design" engineering-blog OO 설계 평가 "절차적이면 항상 나쁘다" 의 증거는 아님 — Fowler 자신이 Transaction Script 도 별도 valid pattern 으로 분류
FOWLER-ANEMIC-C3 Anemic model 은 domain model 의 비용(O/R 매핑 등)을 모두 지불하면서 이득은 못 얻는 구조 [§Cost] "they incur all of the costs of a domain model, without yielding any of the benefits" + [§Cost] "The primary cost is the awkwardness of mapping to a database, which typically results in a whole layer of O/R mapping" engineering-blog JPA/Hibernate 등 O/R 매핑 사용하는 프로젝트 "O/R 매핑이 무조건 비용" 이라는 일반화 아님 — 글 자체가 domain model + O/R 매핑 비교 맥락
FOWLER-ANEMIC-C4 Anemic 구조의 귀결은 Transaction Scripts 가 되어 domain model 의 장점을 잃는다 [§Consequence] "you essentially end up with Transaction Scripts, and thus lose the advantages that the domain model can bring" engineering-blog "domain model 을 채택했다고 표방하는" 코드베이스 Transaction Script 자체가 부적절하다는 뜻은 아님 — Fowler 의 PoEAA 에서 별도 valid pattern
FOWLER-ANEMIC-C5 Domain object 에 위치해야 할 로직 = validations + calculations + business rules [§Domain logic] "The logic that should be in a domain object is domain logic - validations, calculations, business rules" engineering-blog OO 도메인 모델 책임 분배 로깅 / 트랜잭션 경계 / 외부 IO 가 domain 에 와도 된다는 뜻은 아님 (Fowler 가 별도 application/infrastructure layer 분리 권고)
FOWLER-ANEMIC-C6 Eric Evans (DDD) 는 "behavior 를 적절한 객체에 fit 시키는 것을 너무 빨리 포기하고 절차적 프로그래밍으로 점진 회귀하는 것" 을 가장 흔한 실수로 지목 [§Eric Evans 인용] "the more common mistake is to give up too easily on fitting the behavior into an appropriate object, gradually slipping toward procedural programming." engineering-blog (Fowler 의 Evans 인용) DDD 채택 프로젝트의 회귀 패턴 진단 Evans 원전 (DDD 책) 의 정확한 페이지/문단을 본 자료가 명시하지 않음 — Evans 원전 직접 확인 별도 필요

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • FOWLER-ANEMIC-C1~C5: Fowler 가 "Anemic" 을 anti-pattern 으로 명명하고 그 비용/귀결을 진단한 본인 글의 정확한 wording
    • FOWLER-ANEMIC-C6: Fowler 가 Evans 의 입장을 어떻게 요약했는지 (Evans 의 원전 자체 아님)
  • 이 자료가 증명하지 않는 것:
    • Anemic 회피가 "공식 표준 best practice" 라는 정당화 — Fowler bliki 는 본인 의견 글이며 공식 spec/RFC/벤더 doc 아님 (Strength = engineering-blog)
    • ca-tmpl 의 구체 결정 (domain logger ban / safe reason enum / package-private constructor) 의 이름과 메커니즘 — 본 글은 anti-pattern 진단까지만, 구체 구현은 Vernon IDDD 등 별도 자료 결합 필요
    • JPA + Rich Model 의 ORM-friendly 패턴 (no-arg constructor 가시성 / mapper 위치) — Vernon raw/official-docs/domain-vaughn-vernon-aggregate-root 가 별도 근거
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • ArchUnit 룰로 "domain method 가 비어있으면 경고" 같은 정량 임계 (몇 줄 이상이면 OK?) — 본 자료 범위 밖
    • "logger 금지" 가 본 글에서 직접 도출되는지 — 본 글에서는 "domain logic = validation/calculation/business rule" 만 명시 (transport/logger 언급 없음)
    • 한국 백엔드 현장에서 Spring 튜토리얼 default 가 anemic 이라는 관찰 (메모 항목) — 본 글로 증명 불가, 별도 ingest 필요

메모 / Notes (내 프로젝트 해석 — 자료 직접 인용 아님)

  • ca-tmpl과의 매핑:
    • rich model 측 (ca-tmpl 채택): invariant가 constructor/value object에 위치. mutation은 aggregate root method 호출만. domain exception이 사유를 표현.
    • anemic model 측 (ca-tmpl 거부): domain class는 getter/setter만, 모든 logic이 *Service에 위치. ca-tmpl의 "domain logger ban" + "domain exception safe reason"이 anemic을 자연스럽게 거부함 (서비스 측 logger로 다 위임하면 reason enum이 무의미).
  • 한국 백엔드 현장 관찰 (memo, ca-tmpl과 직접 무관):
    • 우아한형제들 기술블로그 "DDD Aggregate" 시리즈(2020-2022)는 Vernon 라인의 Rich Model 권장.
    • Spring 기본 튜토리얼은 종종 anemic 예시 (@Entity + setter + @Service). ca-tmpl은 이 default를 거부.
  • 트레이드오프:
    • rich model은 ORM(JPA)와 마찰: JPA가 reflection으로 객체 생성 → no-arg constructor 필요 → ca-tmpl의 "package-private/protected" 결정으로 해결.
    • rich model은 DTO/Response 변환 layer가 반드시 필요. ca-tmpl의 "domain-to-response direct exposure forbidden" 결정과 일치.
  • 출처 신뢰도: Fowler bliki는 공식 spec이 아니지만 OO/DDD 영역에서 reference standard로 취급되는 글. Strength = engineering-blog (개인 블로그/bliki 형식이므로 official-vendor-doc 으로 격상 금지).

관련 ca-tmpl branch / contract

  • 적용 branch-note:
  • canonical contract 섹션:
    • raw/project-notes/ca-skeleton-operational-contract#19. Domain Application Readiness Contract
  • 대안 그룹: Group G-J — Privacy / File / Domain Modeling (domain modeling)
  • 본 source의 위치: ca-tmpl reference standard — Fowler "Anemic Domain Model" anti-pattern