613. 도메인 주도 설계 (DDD) 기본 구성 (엔티티, VO, 리포지토리)

핵심 인사이트 (3줄 요약)

  1. 본질: 도메인 주도 설계(DDD)의 전술적(Tactical) 설계는, 더러운 DB 쿼리(SQL) 중심으로 비즈니스를 짜던 낡은 관행을 박살 내고 오직 순수한 자바 객체(POJO)들끼리 핑퐁을 치며 비즈니스 룰을 방어하는 '풍부한 도메인 모델(Rich Domain Model)'의 실전 코딩 헌법이다.
  2. 가치: 식별자(ID)가 생명인 **엔티티(Entity)**와 불변성(Immutability)으로 무장한 1회용 찰흙 덩어리 **값 객체(VO, Value Object)**를 레고처럼 조립하고, 이 완성된 객체들을 DB라는 창고에서 꺼내고 넣는 문지기 역할만 **리포지토리(Repository)**에게 전담시킴으로써, 비즈니스 로직이 인프라 똥 냄새에 오염되지 않는 극강의 캡슐화를 이룩한다.
  3. 융합: 이 작은 클래스 단위의 객체 조립술은, 단순한 코드 찢기를 넘어 시스템의 심장부(Domain)를 철통 방어하는 **클린 아키텍처(Clean Architecture, 611장)**의 가장 완벽한 알맹이(Core)로 융합되며 현대 백엔드 엔터프라이즈의 표준 뇌 구조로 안착했다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념: 에릭 에반스(Eric Evans)의 도메인 주도 설계(DDD) 중 '어떻게 코드로 짤 것인가'를 다루는 전술(Tactical) 파트의 핵심 3대장 부품.

    • Entity (엔티티): 고유한 멱살(ID)을 쥐고 있는 생명체. 내가 늙어도 내 주민번호(ID)가 같으면 나는 나다 (동일성 Identity).
    • VO (Value Object, 값 객체): ID 따윈 없는 소모품 쓰레기. 만원짜리 지폐 2장이 있을 때, 그 지폐 번호(ID)가 달라도 '1만원'이라는 값(Value)만 같으면 둘은 똑같은 놈으로 취급한다 (동등성 Equality).
    • Repository (리포지토리): 이 생명체(Entity)와 쓰레기(VO)들을 메모리 컬렉션(List/Map)처럼 다루게 해 주며, 뒤에서 몰래 진짜 오라클 DB에 꽂아주는 하청업체 문지기.
  • 필요성 (빈혈 도메인 모델의 비극): 옛날 주니어 자바 개발자들은 User 클래스를 만들고, 그 뱃속에 private int money; 딸랑 변수랑 get/set 껍데기만 뚫어놨다 (빈혈 도메인 모델, Anemic Domain Model). 그리고 돈 빼는 중요한 비즈니스 로직 계산은 엉뚱하게 UserService 라는 파일에다가 길게 if문 100줄을 쌩코딩 쳐놨다. 1년 뒤, AdminService 라는 파일에서 어떤 미친놈이 User.setMoney(0) 이라고 Setter를 다이렉트로 호출하며 유저 돈을 허공에 날려버렸다!! "아 씨발!! 비즈니스 로직(돈 빼기)을 객체 뱃속(Domain)에 안 가둬놓고 밖(Service)에 흩뿌려놓으니까, 개나 소나 데이터 만지다 털리잖아!! 객체지향 뽕 찼다며 왜 C언어 절차지향처럼 똥 짜고 앉았어?! 데이터와 로직을 무조건 한 몸(Rich Domain)으로 합쳐버려!!" 이 강박적 캡슐화 헌법이 엔티티와 VO를 낳았다.

  • 💡 비유: 빈혈 모델(구식)은 **'머리 텅 빈 지갑(데이터)'과 '계산원(Service 로직)'**입니다. 누구나 지갑을 열어 돈(Getter/Setter)을 쓱 빼갈 수 있어 도둑질에 취약하죠. 풍부한 도메인 모델(DDD)은 **'지문 인식 자판기(Entity)'**입니다. 돈통(데이터)은 자판기 강철 껍데기 속에 꽁꽁 숨겨져 있습니다(private). 유일한 대화 수단은 자판기 앞면의 '음료수 뽑기 버튼(pay())'뿐입니다. 돈을 꺼내는 더러운 로직은 자판기 뱃속(도메인 객체 내부)에서 100% 알아서 굴러가고, 밖에서는 절대로 자판기 배를 가르지 못하는 궁극의 보안 방어술입니다.

  • 등장 배경 및 발전 과정:

    1. Data-Driven (DB 쿼리 중심 시대): SQL이 왕이던 시절. UPDATE user SET money = money - 1 쿼리 한 줄 치는 게 자랑이었다. 자바(Java)는 그냥 DB 껍데기를 웹으로 토스하는 병신 바보 객체(VO/DTO)였다.
    2. Active Record (과도기): "야 자바 객체가 지가 알아서 save() 치게 만들자 ㅋ" (Ruby on Rails). 근데 객체 뱃속에 DB 접속 코드가 떡칠되어 테스팅이 안 되고 뻗음.
    3. DDD Tactical Design (현재): "객체는 오직 순수한 자바(POJO)로만 숨 쉬어야 해! DB 코드는 1바이트도 묻지 마! 대신 비즈니스 룰은 100% 다 뱃속에 박아 넣어!!" (Rich Domain + Repository 찢기). 현대 Spring Boot + JPA 생태계의 교과서로 우화함.
  • 📢 섹션 요약 비유: 이 혁명은 '꼭두각시 인형'에서 '인공지능 로봇'으로의 진화입니다. 옛날 엔티티(빈혈 모델)는 실에 매달린 인형입니다. 서비스(Service) 클래스가 밖에서 실을 100번 당겨야(Getter/Setter) 겨우 움직이죠. DDD의 엔티티는 인공지능 로봇입니다. 뱃속에 스스로 계산하고 판단하는 뇌(비즈니스 로직)가 꽉 차 있습니다. 밖에서는 그저 "청소해!(메서드 호출)" 1마디만 던지면 10초 컷으로 모든 일을 완벽히 오차 없이 지 혼자 끝내버립니다.


Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

1. 3대 부품의 완벽한 찢기 콤보 (Entity / VO / Repository)

① Entity (엔티티) - "생명체 👑"

  • 본질: 고유 식별자(id = 1)가 멱살을 잡는다. 유저가 이름(Name)을 바꾸고 비번을 바꿔도, id=1이면 영원히 똑같은 놈이다.
  • : 생명 주기가 있다 (생성 ➡ 변경 ➡ 삭제). 이 놈 뱃속에 절대 무지성 Setter를 뚫지 마라!! changePassword(old, new) 처럼 완벽한 '의도(Intent)'가 담긴 비즈니스 메서드로만 값을 찔끔찔끔 변하게(Mutable) 허락해라. (602장 정보 은닉 100% 락인).

② Value Object (VO, 값 객체) - "일회용 건전지 🔋"

  • 본질: id 식별자가 없다. 오직 뱃속에 든 값(Value)이 100% 같아야만 같은 객체다.
  • 룰 (불변성 Immutability 💥 핵심): Color(Red, Green), Money(10,000원) 같은 놈들이다. VO 뱃속의 데이터는 태어날 때(생성자) 한 번 쾅! 박힌 뒤엔, 우주가 두 쪽 나도 절대 수정(Setter)될 수 없는 얼음 덩어리여야 한다.
    • Money 객체에 5,000원을 더하고 싶다? 기존 Money 뱃속을 고치는 게 아니라, new Money(15000) 아예 새로운 15,000원짜리 껍데기 객체를 새로 창조해서 뱉어내고 옛날 건 쓰레기통(GC)에 버려야 한다. 스레드 1만 개가 동시에 건드려도 에러 0% 보장하는 극한의 스레드-세이프(Thread-safe) 방어막이다.

③ Repository (리포지토리) - "도라에몽 주머니 📦"

  • 본질: 앞의 Entity 놈들을 창고(DB)에 저장하고 빼오는 마술 지팡이.
  • : 비즈니스 로직(뇌)은 오라클인지 MySQL인지 몰라야 하니까, 무조건 인터페이스 껍데기(interface UserRepository)로 뚫어놔라. (611장 클린 아키텍처 DIP). 그리고 밖에서 JPA 개발자가 save(), findById() 로직을 몰래 쌩코딩 쳐서 주사기(@Autowired)로 푹 주입해 준다.

2. 안티패턴: '기본 타입 집착증(Primitive Obsession)'의 파국 💥

주니어 자바 개발자들이 99% 저지르는 코딩 똥볼.

  • 문제: User 클래스를 짠다. String name;, String email;, String address;. 전부 다 String(원시 타입) 떡칠을 해놨다.

  • 파국: 컨트롤러에서 파라미터 넘길 때 createUser("서울시 강남구", "철수", "a@a.com") 이렇게 순서를 헷갈려서 쳤다. 컴파일러는 전부 다 String이니까 에러를 안 뿜고 200 OK 뱉어버렸다! DB를 까보니 이름이 "서울시 강남구"고 주소가 "철수"로 1만 명의 고객 데이터가 개박살 나버렸다. (타입 안정성 붕괴 대참사).

  • 해결 (VO 포장술의 마술):

    • String을 쓰지 마라! Email, Address 라는 껍데기 클래스(VO)를 새로 하나씩 예쁘게 파라!
    • class Email { private String value; public Email(String val) { 정규식 @ 검사 쾅! } }
    • 1차 방어: 파라미터 순서 헷갈려서 new Email("철수") 넣으면 컴파일러가 빨간 줄 쫙 그어버림(Type-Safe).
    • 2차 방어: Email 객체 태어날 때 생성자 안에서 무조건 @ 있는지 100% 무결점 정규식 검사를 강제(Validation) 치기 때문에, 이 객체가 살아서 굴러다니면 1만 번을 써도 절대 에러가 안 나는 우주 방어 상태가 된다.
  • 📢 섹션 요약 비유: Primitive 떡칠은 **'라벨 없는 약통'**입니다. 하얀 알약(String)이 100개 있는데 이게 두통약인지 설사약인지 구분 안 돼서 먹다 죽습니다. VO 객체로 래핑(포장)하는 건 **'완벽하게 포장된 처방전 약봉투'**입니다. 겉면에 "이메일 전용 캡슐", "주소 전용 캡슐" 명찰(타입)이 시뻘겋게 박혀있고, 뱃속에는 독약(잘못된 정규식)이 절대 못 들어오게 약사가 1차 검수(생성자 검증)까지 다 끝낸, 평생 안심하고 집어먹는 무적의 알약 생태계입니다.


Ⅲ. 융합 비교 및 다각도 분석

1. 객체 3형제 설계 포지션 대결 (Entity vs VO vs DTO)

면접관이 칠판 던져주면 무지성으로 박아야 할 영혼의 3단 분리 표.

척도1. 엔티티 (Entity) 👑2. 값 객체 (VO) 🔋3. 데이터 전송 객체 (DTO) 📦
식별자 (Identity)있음. (id=123)없음. 걍 값이 전부. (1만원)없음. (걍 텍스트 묶음 박스).
수정 가능성가능 (Mutable). (메서드로 살짝살짝 수정 됨).절대 불가능 (Immutable). 수정하려면 죽이고 100% 새로 낳아야 함.걍 게터/세터 열어두고 막 씀.
비즈니스 로직(뇌)존나 많음 (Rich). 내 뱃속에 돈 빼고 더하는 로직 다 쑤셔 박힘.존나 많음 (Rich). 환율 계산, 덧셈 뺄셈 로직 다 뱃속에 있음.로직 0% (Dumb). 걍 변수랑 껍데기만 있는 플라스틱 박스.
활용 위치코어 심장부 (DB 테이블과 매핑 됨).코어 심장부 (엔티티의 팔다리 부품).밖에서 인터넷 API로 쏠 때만(네트워크 통신용) 잠깐 담아 나르는 1회용 박스.

과목 융합 관점

  • 소프트웨어 아키텍처 (클린 아키텍처 611장 융합): 이 3대장(Entity, VO, Repository 껍데기)이 들어가는 방구석이 바로 클린 아키텍처의 가장 안쪽, **정중앙 10점짜리 무적 벙커(Entities Layer)**다!! 이 순결한 자바 파일 3개는 절대 import org.springframework.web 따위의 밖의 쓰레기 똥내를 묻히지 않는다. 내일 당장 스프링을 버리고 딴 걸로 갈아타도 이 중앙 벙커의 파일들은 1바이트의 수정 없이 그대로 복붙 텔레포트 컷오프(Portability)되는 클라우드 네이티브 생존의 절대 척추뼈다.

  • 데이터베이스 공학 (JPA/Hibernate 임베디드 타입 융합): "야 자바 객체(VO)를 Address 로 찢어놓으면, 오라클 DB에는 테이블 어케 만듦? 테이블도 찢음?" ➡ ORM(JPA) 기술의 기적이다. 테이블은 찢지 않는다! 걍 User 테이블 1개 뱃속에 city, street, zip_code 컬럼으로 다 쑤셔 박아둔다. 그리고 JPA에 @Embedded@Embeddable 찰흙 본드 2개를 딱 발라두면? DB에서 데이터 긁어올 때 JPA 엔진이 0.1초 찰나에 3개 컬럼 텍스트를 뭉쳐서 완벽한 1개의 Address(VO) 객체 찰흙으로 얍쌉하게 구워서 자바(Java) 뇌로 꽂아준다!! DB는 가로로 쫙 펴진 1차원 평면(Table) 꿀을 빨고, 자바 뇌는 입체적인 레고 객체(Object) 꿀을 빠는 '객체-관계 임피던스 불일치(Impedance Mismatch)'의 완벽한 타협 봉합술이다.

  • 📢 섹션 요약 비유: 이 JPA 매핑 마술은 **'트랜스포머 장난감 포장'**과 똑같습니다. DB(박스)에 저장할 때는 부피(테이블 Join 렉)를 줄이기 위해 팔다리를 납작하게 쫙 펴서(1차원 컬럼) 보관합니다. 자바 메모리로 꺼내는 순간! 찰칵찰칵 관절이 접히면서 입체적인 멋진 3D 로봇(객체/VO)으로 부활하여 내 눈앞에 뚝 떨어집니다. 보관(DB) 효율과 놀이(Java 코딩) 쾌감을 둘 다 100점 맞은 융합술입니다.


Ⅳ. 실무 적용 및 기술사적 판단

실무 시나리오

  1. 시나리오 — '빈혈 모델(Anemic Model)'과 '거대 서비스(Fat Service)'가 낳은 비즈니스 파편화 대재앙: 주니어들이 코드를 짰다. User 엔티티는 변수만 있고 setMoney()만 뚫어놨다. 1) 유저 결제할 때 OrderService에서 "돈 500원 빼서 저장 ㅋ" 로직을 짰다. 2) 한 달 뒤 이벤트 만들 때 EventService에서 "돈 500원 빼서 저장 ㅋ" 로직을 또 짰다. 3) 반년 뒤, 정책이 바뀌어 "마이너스 통장 잔고 뚫리면 예외 에러 뱉게 방어막 쳐주세요" 오더가 떨어졌다. 주니어는 1번 파일(OrderService)만 고치고 퇴근했다. 다음 날 이벤트 서버(2번 파일)에서 유저 잔고가 마이너스 1억이 뚫리며 회사가 파산했다!! (로직 산탄총 수술 실패).

    • 아키텍트의 해결책: 풍부한 도메인 모델(Rich Domain Model)로의 응집력 멱살잡기(Cohesion) 락인이다. 도끼를 든다. OrderService, EventService에 흩뿌려진 '돈 계산 if-else' 똥 로직을 모조리 가위로 잘라버린다(Extract Method). 그리고 그걸 오직 User 엔티티 본체 클래스의 뱃속에 public void withdraw(int amount) { if(마이너스) 컷!! } 단 1개의 철벽 요새 함수로 몽땅 구겨 넣어 합쳐버린다(Encapsulation). 서비스(Service) 놈들은 걍 밖에서 저 withdraw 함수만 딸깍! 찌르게 짬처리 치면, 내일 룰이 100번 바뀌어도 전사 1만 개의 서비스 파일 중 단 1줄도 안 고치고 오직 저 User.java 1곳만 딱 고쳐서 1초 컷 방어가 끝난다.
  2. 시나리오 — '가변 객체(Mutable VO)'의 참조 주소 유출이 빚은 복제 인간 동시성 파괴: 장바구니에 "빨간색(Color)"을 담았다. Color를 일반 변수(가변)로 짰다. 주문 서버 스레드(A)가 빨간색 객체를 가져가서 처리하고 있는데, 0.01초 뒤 환불 서버 스레드(B)가 갑자기 저 똑같은 빨간색 메모리 주소(Reference)를 훔쳐 가서 color.setName("파란색") 으로 멋대로 덮어씌워 버렸다!! A 스레드는 빨간색인 줄 알고 결제했는데 마지막 영수증에 파란색이 찍혀 나가면서 전사 10만 유저의 데이터 정합성이 우주 끝까지 박살 났다.

    • 아키텍트의 해결책: VO(값 객체)의 완전 불변성(Immutability) 강제 헌법 세팅이다. VO는 우주가 두 쪽 나도 불변이어야 한다!! 아키텍트는 1) 클래스에 final 도장을 쾅 박아서 상속을 막고, 2) 모든 변수에도 final을 떡칠해서 한 번 태어날 때(생성자) 값이 꽂히면 영원히 얼어붙게 만든다. 3) Setter 함수는 싹 다 도끼로 부숴 삭제하고, 오직 값을 뱉는 Getter만 열어둔다. 값을 정 바꾸고 싶다면? public Color changeColor() { return new Color("파란색"); } ➡ 아예 100% 새로운 찰흙 덩어리를 new 복제 생성해서 밖으로 휙 던져줘라!! 기존 빨간색 메모리 주소는 1비트도 안 변했으니 1만 개 스레드가 빨대를 꽂아도 0%의 동시성 레이스 컨디션 방어막(Thread-Safe)이 유지된다.

도입 체크리스트

  • 비즈니스적: "이 도메인이 단순한 'CRUD(게시판 글쓰고 읽기)' 쩌리인가? 아니면 100가지의 예외 케이스와 조건(할인율, 회원 등급, 결제 룰)이 난무하는 복잡계 코어 비즈니스인가?" 단순 게시판 짜는데 Article Entity 파고 Title VO 객체 파고 지랄 염병 치면(Over-engineering) 오버헤드 땜에 배포가 1주일 늦춰져 사장님한테 맞는다. 단순 CRUD는 걍 1통짜리 클래스에 쌩 String 박아서 1초 컷 개발하고 퇴근해라. DDD 엔티티/VO 찢기 칼춤은 오직 **"이 코드에 복잡한 룰(If-else 비즈니스 검증)이 10줄 이상 꼬여 들어가기 시작하는 그 찰나의 티핑 포인트(Tipping Point)"**에서만 들이대야 1년 뒤 유지보수(Maintenance) 비용 복리 이자를 타파하는 극강의 무기가 된다.
  • 기술적: 엔티티(Entity) 뱃속에 무지성으로 DB 식별자 1개(Primary Key) 외에, 논리적 비교 함수(equals / hashCode)를 제대로 덮어씌워 놨는가? User a = new User(id=1), User b = new User(id=1). 2개의 객체를 램에 띄웠다. K8s 파드가 2개라 각자 띄운 거다. 이 둘을 자바 if (a == b) 치면? 메모리 주소(Reference)가 달라서 false 뱉고 로직이 꼬여 터진다!! 아키텍트는 반드시 엔티티 뱃속에 equals() 흑마법을 오버라이딩(Override) 쳐서 "메모리 주소가 달라도 뱃속의 고유 id 숫자만 똑같으면 우주가 두 쪽 나도 무조건 같은 놈(true)으로 취급해라!!" 라는 논리적 일치 헌법을 세팅해 둬야 JPA 엔진(영속성 컨텍스트)과 Set/Map 자료구조 안에서 버그 없이 무결점으로 객체가 굴러간다.

안티패턴

  • "JPA/Hibernate 프레임워크 핑계로 엔티티(Entity)에 @Data 나 무지성 Setter를 도배해버리고 캡슐화 포기하기 (JPA Slaves)": "아 JPA 쓰려면 기본 생성자(public User())랑 Setter 다 열어둬야 편하게 DB에서 긁어오잖아요 ㅋ" 프론트 핑계, DB 핑계 대면서 캡슐화 포기하는 주니어들의 1순위 타락. 1주일 뒤, 코드 사방팔방에서 user.setMoney() 빨대가 꽂히며 스파게티 지옥 똥통으로 환생한다. "명심해라. JPA 엔진을 핑계 대지 마라. JPA가 리플렉션(Reflection)으로 객체 쑤셔 넣을 때 Setter 따윈 1도 필요 없다! 무조건 protected User() (패키지 내에서만 살짝 허용)로 빈 깡통 생성자를 꽁꽁 숨기고, 나머지 생성 룰은 @Builder 패턴(604장)이나 완벽히 통제된 팩토리 메서드(Static Factory Method) 대문 딱 1개만 열어두는 철통 캡슐화 보안을 목숨 걸고 사수해야 도메인 뇌가 썩지 않는다."

  • 📢 섹션 요약 비유: 엔티티에 무지성 Setter를 여는 짓은, **'집 현관문을 다 뜯어버리고 "택배 기사님 짐 놓기 편하게 그냥 대문 활짝 열고 잘게요 ㅋ" 쿨하게 쳐자는 짓'**입니다. 택배 기사(JPA)는 편하겠지만, 그날 밤 도둑 10명(다른 팀 버그 코드)이 쳐들어와 내 집 돈(데이터)을 다 훔쳐 갑니다. 진정한 아키텍트는 현관문(캡슐화)을 10cm 티타늄으로 걸어 잠그고, 택배 기사 전용 '작은 우유 투입구(빌더 패턴/팩토리 1개)' 딱 1개만 파서 거기로만 짐을 100% 안전하게 받아내는 편집증적 통제술의 끝판왕입니다.


Ⅴ. 기대효과 및 결론

정량/정성 기대효과

구분String, int 떡칠 + Service에 로직 1만 줄 쌩코딩 시절Entity/VO 캡슐화 + Rich Domain Model 뇌 이식 (TO-BE)개선 효과
정량Null 체크 및 타입 오류(String 오타)로 인한 런타임 버그율 20%VO 생성자에서 100% 예외 컷오프(Fail-fast) ➡ 버그 통과율 0.1% 미만런타임 인프라 치명적 에러 및 데이터 오염(Corruption) 방어율 99% 극대화
정량로직 수정 시 Service 클래스 100군데 Ctrl+F 검색 변경 (3일 소요)Entity 객체 내 1개 메서드 5줄만 변경하면 전사 1초 컷 핫스왑 동기화비즈니스 룰 갱신 리팩토링 리드타임(Lead Time) 및 회귀 테스트 90% 삭감
정성"야 결제 로직 어디 있어? PaymentService 뒤져도 안 보이네 ㅠ""걍 Payment.java 엔티티 열면 그 안에 덧셈뺄셈 다 예쁘게 박혀있음 ㅋ"코드 응집도(Cohesion) 우주 돌파로 신규 입사자 도메인 파악 온보딩 1일 컷

미래 전망

  • Record (자바 14+) 문법의 도래와 VO 쌩노가다의 멸종: 옛날엔 VO(값 객체) 하나 만들려면 1. private final 박고, 2. 생성자 길게 파고, 3. equals(), hashCode(), toString() 100줄을 땀 흘리며 쌩코딩 하거나 Lombok 떡칠을 해야 했다. 개귀찮았다. 자바 14부터 이 귀차니즘을 박살 낼 구세주 Record 헌법이 등판했다. public record Money(int amount, String currency) {} 코드 딱 1줄 엔터 치면 끝난다!! JVM이 뱃속에서 final, equals(), hashCode() 흑마법 1만 줄을 0.01초 컷으로 자동 생성 렌더링 쳐서 뱉어준다. 보일러플레이트 코드가 1/100로 증발하며 DDD(VO) 패턴 도입의 유일한 진입 장벽(노가다)이 지구상에서 완전히 파괴되었다.
  • Event Sourcing (이벤트 소싱 555장)과의 융합 폭발: 이 DDD 엔티티와 리포지토리가 미래엔 어떻게 진화할까? 지금 리포지토리는 엔티티 상태를 오라클 DB에 UPDATE 쳐서 덮어쓰고 과거를 날려버린다(CRUD의 멸망). 차세대 최전방 아키텍처(이커머스/금융)는 이 엔티티의 상태(State)가 바뀔 때마다 555장 이벤트 소싱(Event Sourcing) 댐을 뚫는다. 엔티티에 덮어쓰지 마라! OrderCreated(100원), OrderCanceled(-100원) 텍스트 쪽지들만 Kafka 큐에 미친 듯이 100만 장 흩뿌린다(Append-only). 리포지토리는 나중에 이 쪽지 100만 장을 빨대 꽂아 순서대로 스피드 덧셈 뺄셈(Replay) 쳐서 0.01초 만에 최신 엔티티 찰흙 덩어리를 허공에서 부활(Hydration)시켜 내는 무결점 시계열 블록체인급 뇌 구조로 통일되어 가고 있다.

참고 표준

  • Domain-Driven Design (Eric Evans): "DB 쿼리(Data-driven) 깎는 늙은이 짓 좀 그만하고, 제발 소프트웨어의 뇌를 객체(Domain) 위주로 생각해서 짜라 이 멍청이들아!!" 에릭 에반스가 2003년 전 세계 개발자의 멱살을 잡고 뺨을 치며, 엔티티/VO/애그리게이트라는 객체지향 최강의 철학적 무기를 내려준 인류 IT 공학 최고의 바이블 성경.
  • Vaughn Vernon의 Implementing DDD: 에릭 에반스 책이 너무 철학적이고 뜬구름 잡는 소리라 빡친 반 버논이 "야 내가 실전 자바(Java) 코드로 어떻게 Entity 파고 VO 파는지 밑바닥 폴더 구조부터 예쁘게 다 깎아서 족보 템플릿(Red Book)으로 퍼먹여 줄게 ㅋ" 라며 실무자들에게 한 줄기 빛을 내려준 프랙티컬 끝판왕 도서.

도메인 주도 설계 (DDD) 기본 구성 (엔티티, VO, 리포지토리)은 소프트웨어 공학이 도달한 **'무지성 데이터(DB 찌끄레기) 중심의 타락한 쿼리(SQL) 깎기 노예 생활을 도끼로 끊어내고, 우리의 비즈니스 로직(돈을 버는 뇌) 그 자체를 코드의 최전방 1짱 권력자(Rich Domain Model)로 수직 상승시켜 세운 궁극의 캡슐화 신정(神政) 정치'**다. 우리는 지난 수십 년, 멍청한 바보 깡통 객체(DTO/빈혈 모델)를 만들어놓고 밖에서 수천 줄의 Service 코드가 그 배를 갈라 변수를 쑤셔 넣고 빼는 잔인한 스파게티 지옥(Tight Coupling)에 살았다. 그 결과 결제 룰 하나가 바뀔 때마다 전사 100개의 서비스 파일이 연쇄 폭발(Ripple Effect)하며 회사의 심장을 멈춰 세웠다. 아키텍트는 분노어린 철창을 내려친다. 흩어진 로직의 똥들을 모조리 긁어모아 '엔티티(Entity)'라는 신성한 객체의 뱃속에 폭압적으로 욱여넣고 밀봉(private)해 버려라. 이 생명체는 이제 밖에서 "돈 까라(withdraw)"는 우아한 메시지 1줄에만 반응하며 자기 스스로 방어막(Validation)을 치고 오차 없이 계산을 쳐낸다. 변하지 않는 소모품 속성들은 '값 객체(VO)'라는 단단한 티타늄 캡슐로 감싸 1만 개의 스레드가 찔러도 0%의 버그를 뱉는 스레드-세이프(Thread-safe) 방탄유리로 코팅한다. 그리고 이 아름답고 튼튼한 뇌세포 덩어리들이 완성되면, 그제야 무식한 노가다 하청업자(Repository)에게 던져주어 어둠 속 창고(DB)에 조용히 묻어두게 짬처리(Offloading) 시킨다. 도메인(뇌)은 DB(인프라)를 모르고, 오직 비즈니스의 진리만 읊조린다. 10년 뒤 오라클 디비가 멸망하고 클라우드 우주선 50대(MSA)로 서버를 찢어 발기는 그 최후의 심판 날에도, 이 순백의 도메인 덩어리 3형제만큼은 1비트의 수정조차 없이 통째로 텔레포트되어 새 우주(K8s)의 심장부로 화려하게 이식될 영원한 불멸성(Portability)의 엑스칼리버다.

  • 📢 섹션 요약 비유: 빈혈 모델(구식) 코딩은 **'로봇 장난감의 팔, 다리, 모터(데이터)를 거실 바닥에 쫙 널브러뜨려 놓고, 아빠(Service 로직)가 직접 손으로 하나하나 잡아서 수동으로 움직여주는 짓'**입니다. 아빠가 퇴근을 못 하면 장난감은 멈춥니다(스파게티 유지보수 지옥). DDD 뼈대 코딩은 **'건전지(VO)와 모터, 칩(비즈니스 로직)을 로봇(Entity) 뱃속에 완벽하게 내장(캡슐화) 조립해 버린 완성형 오토-장난감'**입니다. 아빠는 소파에 누워서 "걸어가!" 스위치(메서드 호출)만 딸깍 누릅니다. 로봇 뱃속에서 자기가 알아서 균형을 잡고 완벽한 각도로 오차 없이 걸어갑니다. 아빠(개발자)의 노가다는 0에 수렴하고 로봇의 지능은 100점 만점으로 폭발하는 완전한 독립 권력의 수립입니다.

📌 관련 개념 맵 (Knowledge Graph)

개념 명칭관계 및 시너지 설명
클린 아키텍처 (Clean Architecture)DDD 엔티티가 들어가는 완벽한 안전 벙커. 클린 아키텍처의 가장 정중앙(10점) 킹갓 과녁에 들어가는 파일들이 바로 이 DDD의 Entity와 VO 덩어리들이다. 이 파일들 뱃속에 바깥세상의 프레임워크 똥(Spring)이 1바이트라도 묻으면 과녁판이 개박살 난다. (이전 장 611번 연계)
애그리게이트 (Aggregate Root)Entity 수백 개를 파놓고 서로 1:1, 1:N 거미줄 화살표로 얽어놓으면(JPA 강결합) 나중에 메모리(RAM) 터져서 즉사한다. 10개의 엔티티를 하나의 '비닐봉지(애그리게이트)'에 가두고 밖에서는 무조건 봉지 대빵(Root)만 찌르게 통제하는 극한의 군대식 조직 찢기 사상. (다음 장 615번 연계)
마이크로서비스 아키텍처 (MSA)서버 50개(파드)를 찢으려면 무슨 기준으로 찢어야 할까? 기획자랑 사다리 타기 할 건가? DDD가 그어준 534장 '바운디드 컨텍스트(Bounded Context)'와 애그리게이트 단위가 칼로 자르듯 완벽한 파드 1개 1개(마이크로서비스)의 경계선 사이즈가 되어 K8s 인프라 단위로 100% 흡수 맵핑된다. (이전 장 532, 534번 연계)
캡슐화 및 정보 은닉 (Encapsulation)Entity와 VO를 짜는 핵심 0순위 헌법(602장). 무지성 getter/setter 1개 뚫는 순간 도메인 모델은 배때기가 갈려 좀비 빈혈 모델로 타락한다. 값을 직접 건드리지 못하게 철창(private) 치고 랩핑 치는 게 전술적 설계의 99%다. (이전 장 602번 연계)
이벤트 소싱 (Event Sourcing)"Entity 변수 1개 바꿀 때마다 DB UPDATE 치는 거 지겹다!! 그냥 555장 룰대로 'VO 값 객체'들을 쪽지로 무한 생성(Append)해서 Kafka 큐에 흩뿌려버리자!!" DDD가 K8s 클라우드 빅데이터 세상과 만나면서 진화한 궁극의 CQRS 융합 비동기 상태 저장 아키텍처. (이전 장 555번 연계)

👶 어린이를 위한 3줄 비유 설명

  1. 내가 레고 자동차(데이터)를 만들었는데, 자동차가 스스로 달릴 능력이 없어서 내가 직접 손으로 밀고 바퀴를 굴려줘야만 했어요 (빈혈 모델/Service 노가다 ㅠㅠ).
  2. 그래서 나는 엄청 똑똑하게! 자동차 뱃속에 '초강력 배터리(VO)'랑 '스스로 생각하는 스마트 엔진(비즈니스 뇌/Entity)'을 완벽하게 숨겨 넣고 뚜껑을 꽉 닫아버렸어요 (캡슐화)!
  3. 이제 나는 소파에 앉아서 리모컨으로 "출발해!(명령)" 버튼 하나만 딸깍 누릅니다. 자동차 뱃속의 천재 엔진이 알아서 속도를 조절하고 장애물을 피해 씽씽 달리는 짱 멋진 인공지능 로봇 마법을 'DDD 도메인 모델'이라고 부른답니다!