Files
llm-wiki/raw/blog-topics/domain-modeling-guardrails-as-archunit-fitness-functions-2026-06-05.md
T

5.3 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label, target_audience, inspiration_url, archive_url
title source_type status related_branches related_projects tags created status_label target_audience inspiration_url archive_url
blog-topic / domain-modeling-guardrails-as-archunit-fitness-functions-2026-06-05 blog-topic raw
feature-domain-modeling-guardrails
ca-tmpl
blog-topic
ca-tmpl
archunit
fitness-function
ddd
value-object
aggregate
domain-event
jqwik
clean-architecture
2026-06-05 ready-for-canonical backend-engineer

blog-topic: domain-modeling-guardrails-as-archunit-fitness-functions-2026-06-05

Layer: raw/blog-topics/ — 작업·트러블슈팅에서 나온 글감 원석. canonical 정제 전 raw.

Parent

한 줄 글감

"DDD 전술 패턴을 README 권고가 아니라 빌드 깨짐으로 강제하기 — stereotype 애너테이션 + ArchUnit fitness function."

본문 뼈대 (초안)

  1. 문제: rich domain model / 값 객체 불변식 / transport-free 도메인 이벤트는 보통 "문서 권고"로 남고 시간이 지나면 침식된다(anemic 회귀, public setter, 도메인에 Kafka 타입 누출).
  2. 접근: 의미를 드러내는 마커 애너테이션을 도메인 코어에 둔다 — @ValueObject/@AggregateRoot/@DomainEvent (java.lang.annotation 만 의존, 프레임워크 0).
  3. 강제: ArchUnit 규칙이 마커를 키로 평가
    • value_objects_have_no_public_no_arg_constructor — 빈 생성자 = 불변식 우회 백도어 차단. record(컴포넌트 보유)는 자동 충족.
    • aggregate_root_setters_are_not_publicset* 비공개 강제(Vernon Option A: ORM 외부 매핑 가시성).
    • domain_events_are_records + domain_events_are_transport_free — immutable record + Kafka/HTTP/JAX-RS 패키지 의존 금지.
    • domain_has_no_logger — 도메인은 로그 대신 안전한 명사형 reason enum 예외로 위반을 표현.
  4. owner 경계 교훈: "도메인 순수성" 규칙(다른 branch 소유)에 logger 금지를 끼워넣지 않고 별도 규칙으로 분리한 이유 — 규칙 소유권/위반 메시지 명확성.
  5. 정직성 교훈: logger 금지는 공식 표준이 아니라 프로젝트 자체 규약. 사실 등급을 격상하지 않는다.
  6. 비공허(non-vacuous) 증명: 규칙마다 의도적 위반 fixture + 격리 코퍼스로 "실제로 잡는다"를 테스트(violations-as-data). transport glob 은 broker별 격리 증명.
  7. 함정: testCompileOnly 타입을 record component 로 쓰면 JUnit discovery 가 죽는다 → method body .class 참조로 회피(raw/errors/archunit-testcompileonly-class-loading-2026-06-02).
  8. 불변식 검증의 깊이: 예시 테스트 대신 jqwik property-based test 로 값 객체 입력 공간 전체를 무작위 검증.
  9. 이벤트 경계 PoC: WorkLogReserved(domain) → WorkLogReservedIntegrationEvent(application mapper) — 도메인은 wire 를 모른다.

트리거 / Trigger

글감 / Topic seed

  • 한 문장 요지: DDD tactical pattern을 README 권고가 아니라 marker annotation + ArchUnit fitness function으로 빌드 단계에서 강제한다.
  • 예상 제목 후보:
    • DDD guardrail을 ArchUnit fitness function으로 만들기
    • Value Object와 Domain Event 규칙을 빌드에서 검증하기

핵심 주장 후보 / Claim candidates

  • 사실 후보:
    • @ValueObject, @AggregateRoot, @DomainEvent 같은 marker를 ArchUnit rule의 평가 key로 쓴다.
  • 의견/해석 후보:
    • domain modeling 규칙은 공식 표준이 아니라 project-local guardrail이므로 사실 등급을 조심해야 한다.

Outline seed

  1. tactical DDD rule이 문서 권고로만 남을 때 침식되는 경로를 설명한다.
  2. framework-free marker annotation과 ArchUnit rule의 역할을 나눈다.
  3. violations-as-data와 jqwik property test로 guardrail이 실제로 bite하는지 확인한다.

Canonical 전환 후보 / Canonical extraction candidates

  • wiki/projects/ca-tmpl/clean-architecture-package-layout.md 후보:
    • domain modeling guardrail / ArchUnit fitness function 글감.
  • 필요한 추가 검증:
    • 현재 marker annotation, ArchUnit rule, jqwik test 존재 여부.

Sources / 근거 후보

미해결 / Unknown

  • 아직 확인해야 할 사실: domain guardrail 구현과 property-based test의 현재 상태.
  • 과장하면 안 되는 부분: logger ban이나 marker taxonomy를 DDD 공식 표준처럼 쓰지 않는다.

Decision / 처리 결정

  • 액션: promote-to-canonical
  • 이유: wiki/projects/ca-tmpl/clean-architecture-package-layout.md 에 domain modeling guardrail 글감으로 반영한다.
  • 다음 단계: blogify 전 project-local rule과 구현 증거를 분리한다.