모놀리식 환경에서 DDD 구조로 Order 도메인 설계하기 (UUID, PK, Index 정리)

한소연·2026년 2월 26일

내일배움캠프

목록 보기
3/21
post-thumbnail

현재 팀 프로젝트에서 모놀리식 아키텍처 기반 DDD(Domain-Driven Design) 구조로 설계를 진행하고 있다.
그 과정에서 UUID, PK, FK, Index 개념이 헷갈렸던 부분을 정리해보았다.


1. 프로젝트 구조 방향

✔ Monolithic + DDD

MSA가 아닌 모놀리식 구조이지만,
도메인 중심으로 레이어를 분리하는 DDD 구조를 채택했다.

예시 구조

order
 ├── domain
 │    ├── Order
 │    ├── OrderItem
 │    └── repository
 ├── application
 │    └── OrderService
 ├── infrastructure
 │    └── OrderRepositoryImpl
 └── presentation
      └── OrderController
  • domain → 핵심 비즈니스 로직
  • application → 유스케이스
  • infrastructure → DB 접근
  • presentation → API

2. 왜 UUID를 PK로 사용했는가?

기존 방식은 보통:

id BIGINT AUTO_INCREMENT

이번 프로젝트에서는:

id UUID

UUID를 선택한 이유

  • 분산 환경 확장 가능성 고려
  • 클라이언트에서 ID 생성 가능
  • 보안상 연속 증가 ID 노출 방지
  • MSA 전환 가능성 대비

예시:

550e8400-e29b-41d4-a716-446655440000

3. Order / OrderItem 도메인 설계

3-1. Order (Aggregate Root)

컬럼설명
order_id (PK, UUID)주문 고유 ID
order_status주문 상태
total_price총 금액

Order는 하나의 Aggregate Root이다.


3-2. OrderItem (Entity)

컬럼설명
order_idx (PK, UUID)주문 상세 고유 ID
order_id주문 참조용
menu_id메뉴 ID
quantity수량
subtotal_price소계 금액

4. 왜 OrderItem에 별도의 PK(order_idx)를 두는가?

처음 가졌던 의문:

menu_id를 PK로 쓰면 안 되나?

❌ menu_id는 중복될 수 있다

한 주문에 같은 메뉴가 여러 번 들어갈 수 있다.

order_idmenu_idoption
O1M1얼음많이
O1M1얼음적게

menu_id는 고유하지 않다.


❌ order_id도 중복된다

한 주문에는 여러 개의 주문 상세가 존재한다.

order_idmenu_id
O1M1
O1M2

order_id 역시 중복된다.


✅ 그래서 order_idx를 둔다

OrderItem의 각 행을 고유하게 식별하기 위해
별도의 PK(UUID)를 둔다.

order_idx UUID PRIMARY KEY

이 값은:

  • 중복 불가
  • NULL 불가
  • 자동 인덱스 생성

5. PK와 Index의 관계

PK를 생성하면 자동으로 Index가 생성된다.

즉,

PK는 "고유 식별자"
Index는 "검색 속도 향상 도구"

PK는 기본적으로 인덱스를 포함한다.


6. 복합 PK 대신 단일 PK를 선택한 이유

복합 PK 예시:

PRIMARY KEY (order_id, menu_id)

문제점:

  • JPA에서 복잡
  • 수정 어려움
  • 유지보수 비용 증가

단일 PK:

order_idx UUID PRIMARY KEY

장점:

  • 단순함
  • ORM 친화적
  • 실무에서 가장 많이 사용

7. DDD 관점에서의 정리

  • Order는 Aggregate Root
  • OrderItem은 Order에 속한 Entity
  • OrderItem은 자체 생명주기를 가지므로 고유 PK 필요
  • 외부에서는 Order를 통해서만 접근

8. 핵심 깨달음

처음에는 이렇게 생각했다:

"같은 메뉴를 여러 번 넣기 위해 PK를 따로 둔 건가?"

하지만 실제 이유는:

OrderItem이라는 '엔티티 자체'를 고유하게 식별하기 위함이었다.

DDD에서는
테이블이 아니라 도메인 객체를 기준으로 설계해야 한다는 점을 배웠다.


9. 최종 정리

  • UUID는 확장성과 보안을 위한 선택
  • PK는 행을 유일하게 식별
  • PK 생성 시 자동 인덱스 생성
  • OrderItem은 고유 식별자가 반드시 필요
  • FK를 강제하지 않아도 논리적 참조는 가능
  • DDD에서는 Aggregate 경계를 먼저 생각해야 한다

마무리

이번 설계를 통해 느낀 점은:

DB 중심 사고가 아니라
도메인 중심 사고로 전환하는 것이
DDD의 핵심이라는 것.

앞으로는 테이블 구조보다
이 객체의 책임과 경계를 명확히 하기 위해서
"이 객체는 왜 존재하는가?"를 먼저 고민하려 한다.

profile
안 되면 될 때까지

0개의 댓글