[실전 지식] DDD와 DDD-lite

이세준·2025년 12월 1일
post-thumbnail

? 이게왜 DDD야?

아주 좋은 질문이에요.
지금 구조가 “정통 DDD”라고 보긴 어렵지만, DDD의 패키지 구성 철학을 부분적으로 따른 구조라고 설명하는 것이 정확합니다.
왜 그렇게 보냐면, DDD는 단순히 패키지 구조가 아니라 도메인 모델 중심의 설계 방식이기 때문입니다.

아래에서 명확히 정리해줄게요.


1. 이 구조가 왜 “DDD스럽다”고 말하는가?

DDD(도메인 주도 설계)에서 가장 중요한 개념은 아래와 같아요.

  • 도메인을 중심으로 코드 구조를 잡는다
  • UI, Infra 중심이 아니라 업무 개념을 중심으로 패키지를 나눈다
  • Entity, Value Object, Repository, Service 등 도메인 레이어 개념을 분리한다.

지금 제안한 구조는 다음 특징을 가지고 있습니다.

✔ 1) product(상품)이라는 “업무 개념” 단위로 패키지를 나눔

domain/product
domain/user
domain/order

이처럼 특정 기능(상품 관리, 주문, 결제)별로 나누는 방식은 기능 중심(feature-based)이자 도메인 개념 중심(domain-oriented)입니다.

SRP(단일 책임 원칙)과 함께 모듈성을 높이는 방식인데, 이는 DDD 패키징 방식과 매우 유사합니다.

✔ 2) entity, repository, service를 도메인 안에 배치

DDD는 도메인의 내부에 아래 개념들을 둡니다.

  • Entity
  • Value Object
  • Domain Service
  • Repository interface
  • Domain Event
  • Aggregate

제안한 구조도 동일하게 따라갑니다.

✔ 3) ProductStatus처럼 Enum(도메인의 언어)을 “constant” 레이어에 둠

도메인 용어(Ubiquitous Language)를 코드로 명시적으로 반영하는 것도 DDD 스타일입니다.


2. 그럼 이 구조가 정통 DDD인가?

아니에요.

정통 DDD에서는 아래 요소가 더 명확히 나타나야 합니다:

  • Aggregate Root (Product?)
  • Value Object 식별
  • Domain Service 존재
  • Application Service와 Domain Service의 분리
  • Infrastructure 계층 분리
  • Domain Event 모델링

지금 구조는 "Layered architecture + Feature-based packaging" 조합에 가깝습니다.
하지만 "도메인 개념 기반으로 구성한 패키지"라는 점 때문에 DDD 스타일로 불리고 있는 것이죠.

즉,

정통 DDD는 아니지만, DDD 철학(도메인 중심 조직 구조)을 따른 패키징이다.


3. "DDD냐 아니냐"를 나누는 기준

항목지금 구조정통 DDD
도메인 기준 패키지 구성✔ 존재✔ 필수
Entity/Repository/Service 분리
VO, Aggregate 모델링❌(아직 없음)
Application Service 분리
Domain Event
Infra 계층 분리

그래서 구조 자체만 놓고 보면 “DDD 풍 구조"라고 보는 것이 정확합니다.


4. 그럼 이걸 뭐라고 부르는 게 가장 정확할까?

정확한 명칭은 아래 둘 중 하나입니다.

① Feature-Oriented Layered Architecture

(feature/도메인 단위로 모듈화한 레이어드 구조)

② DDD-Lite / DDD-inspired package structure

(DDD 영향을 받은 패키지 구조)

즉, DDD 구현을 위한 좋은 출발점이지, DDD 자체는 아니다.


5. 결론

정리하면 다음처럼 말하는 것이 가장 정확합니다.

“지금 구조는 DDD의 핵심 철학인 ‘도메인 중심 조직화’를 따른 구조이며,
업무 단위로 도메인을 나눴다는 점에서 DDD 스타일 패키지 구성이라고 볼 수 있다.
하지만 정통 DDD의 전부를 구현한 것은 아니므로 ‘DDD 기반’ 또는 ‘DDD 영향을 받은 구조’라고 부르는 것이 적절하다.”


? 그럼 정통 DDD로 바꾸는걸 추천해?

결론부터 말하면 지금 상황에서는 정통 DDD로 바꾸는 걸 추천하지 않습니다.
대부분의 실무에서는 “DDD-lite(DDD 영향받은 구조)”만으로도 충분하며, 정통 DDD는 오히려 과한 구조적 비용이 들어갑니다.

아래에서 왜 그런지, 언제 정통 DDD가 필요한지 아주 명확하게 정리해줄게요.


1. 정통 DDD는 언제 필요한가?

정통 DDD는 다음 조건에서만 ‘효율적’입니다.

✔ 도메인이 아주 복잡할 때

  • 여러 개의 Aggregate
  • 도메인 규칙이 많고 변경이 잦고
  • 트랜잭션 경계가 복잡한 대기업 서비스

✔ 여러 팀이 동시에 개발할 때

도메인 모델을 공유하지 않으면 충돌이 남.

✔ 이벤트 기반 아키텍처, CQRS, MSA 등과 결합할 때

정통 DDD는 사실상 분산 시스템이나 대규모 시스템에서 빛을 발함.


2. 하지만 정통 DDD는 비용이 매우 크다

정통 DDD를 적용하면 아래 작업들이 필수로 따라옵니다:

❌ Application Layer / Domain Layer / Infra Layer 분리

→ 코드가 2~3배 길어짐
→ 파일이 폭증함

❌ Domain Service vs. Application Service 구분

→ 의미를 아는 사람이 적으면 오히려 복잡해짐

❌ Event 모델링, VO 정교화

→ 작은 프로젝트에서 과설계가 됨

❌ Repository interface + Infra implementation

→ 초반 개발 속도 크게 느려짐

즉,

정통 DDD는 “개발비용이 높은 설계 방법론”이다.
스타트업, 개인 프로젝트, 단일팀 프로젝트에서는 비효율적이다.


3. 너의 현재 상황 기준으로 판단

너는 지금:

  • 상품, 주문, 분석 등 여러 기능을 만들고 있음
  • 개인 / 소규모 개발
  • Node.js 기반 서비스 구조 설계
  • 복잡한 도메인이긴 하지만 "초기 설계 단계"

이 상황이라면 아래가 맞습니다.

→ 정통 DDD는 과함

→ DDD-lite(도메인 중심 패키지 구조)만으로 충분

→ 실제 도메인이 복잡해지면 그때 점진적으로 DDD 요소 확장

지금은 유연하고 단순한 구조가 훨씬 더 가치 있음.


4. 그럼 너한테 딱 맞는 추천은?

✔ 추천: “DDD 스타일 패키징 + 단순 레이어드 서비스”

현재 구조처럼:

domain/product
   ├── entity
   ├── dto
   ├── repository
   ├── service
   └── controller

이 구조는 다음 이유로 베스트:

  • 도메인이 커져도 구조 유지 가능
  • 정통 DDD보다 파일과 계층이 적어 효율적
  • 개선할 때 Aggregate, VO 등 서서히 도입할 수 있음
  • 스타트업·기능 확장에 적합

❌ 비추천: 정통 DDD 전체 도입

  • 개발 속도 ↓
  • 필요 없는 개념을 억지로 설계하게 됨
  • 기능 만드는 데 오히려 방해됨

5. 내가 제안하는 로드맵

정통 DDD로 갈지 말지 고민된다면 아래가 베스트 접근입니다:

Step 1. 현재처럼 도메인 패키지 구성 유지 (지금이 정답)

Step 2. 도메인 로직이 쌓이면 VO 도입 (Money, Period 같은 것)

Step 3. 트랜잭션 경계 복잡해지면 Aggregate 개념 도입

Step 4. 이벤트 흐름이 많아지면 Domain Event 도입

Step 5. 규모가 커진다면 Application Layer 분리 검토

→ 즉, 필요할 때만 DDD 요소를 가져오는 방식이 정답입니다.


6. 결론

너의 현재 개발 상황에서는 정통 DDD로 바꾸는 것보다
도메인 기반 패키지 구조(DDD-lite)로 가는 것이 훨씬 합리적이고 실용적이다.

정통 DDD는 필요해지면 “부분적으로” 확장해도 충분하다.


? DDD 스타일 패키징 + 단순 레이어드 서비스 에 대해 기초적으로 설명해줘

아주 쉽게, 기초 개념 중심으로 정리해줄게.
“DDD 스타일 패키징 + 단순 레이어드 서비스”는 DDD 전체를 적용하지 않고,
DDD의 핵심인 도메인 중심 구조만 가져오고,
서비스 구조는 전통적인 레이어드 아키텍처처럼 단순하게 유지하는 방식이다.

즉,

복잡한 도메인 모델링은 아직 필요 없지만, 도메인 단위로 코드를 정리하고 싶을 때 쓰는 현실적인 아키텍처 방식.

아래에서 아주 기초부터 설명해줄게.


1. 기본 개념: 레이어드 아키텍처(Layered Architecture)

전통적으로 가장 많이 쓰이는 구조.
코드는 계층(layer) 단위로 나뉨:

1) Controller layer

  • HTTP 요청을 받음
  • DTO 변환
  • service 호출만 함

2) Service layer

  • 비즈니스 로직을 처리
  • repository 호출
  • 트랜잭션 관리

3) Repository layer

  • DB와 연결
  • CRUD 담당

4) Entity layer

  • DB 테이블을 객체 형태로 표현
  • 도메인 데이터 구조

이게 기본 레이어드 구조야.


2. 문제점: 패키지를 레이어별로 묶으면 도메인 중심이 아님

전통적 방식은 이렇게 생김:

controller/
service/
repository/
entity/

이런 구조의 문제:

  • 상품 도메인을 이해하려면 controller, service, entity, repo를 왔다 갔다 해야 함
  • 팀 규모가 커지면 각 도메인별 구조가 뒤섞임
  • 변경 영향 범위 파악이 어려움

즉, 조직적으로 묶여 있을 뿐, 도메인적으로 묶여 있지 않음.


3. DDD 스타일 패키징의 핵심

DDD에서의 핵심 철학은 “도메인 단위로 코드를 묶어라”는 것.

그래서 패키지가 아래처럼 됨:

domain/product
   ├── controller
   ├── service
   ├── repository
   ├── entity
   └── dto
domain/order
   ├── ...
domain/user
   ├── ...

즉,

하나의 도메인에 필요한 Controller, Service, Repository, Entity를
한 폴더(모듈) 안에 넣는 구조.

이러면 장점이 명확함:

  • 특정 도메인 코드를 한곳에서 볼 수 있어 이해가 쉬움
  • 도메인마다 독립성이 높아짐 (모듈화 ↑)
  • 확장/유지보수 편리
  • 패키지 자체가 “바운디드 컨텍스트”처럼 작동함

그래서 "DDD 스타일의 패키징"이라고 부르는 것.


4. 하지만 서비스 구조는 “단순 레이어드 방식”을 유지한다

여기서 포인트는 서비스 계층은 단순하게 유지한다는 것.

정통 DDD에서는:

  • 애플리케이션 서비스
  • 도메인 서비스
  • 애그리게이트
  • 밸류 오브젝트
  • 도메인 이벤트
  • 리포지토리 인터페이스
  • 인프라 구현체

등이 구분되면서 구조가 많이 복잡해짐.

하지만 여기서는 그런 복잡한 계층 구분을 하지 않고,

서비스는 단순하게 유지:

domain/product
   ├── controller
   ├── service (ProductService.java)
   ├── repository (ProductRepository.java)
   ├── entity (Product.java)
   └── dto

서비스는 아래 역할만 함:

  • 비즈니스 로직 처리
  • 엔티티 생성/수정
  • Repository 호출
  • 트랜잭션 처리

즉, 전통적인 레이어드 서비스 구조 그대로.


5. 이를 합치면?

둘을 합치면 다음과 같이 된다:

✔ DDD 스타일 패키징

→ 도메인(feature) 단위로 모듈화
→ product/order/user처럼 논리적으로 묶음

✔ 단순 레이어드 서비스

→ controller → service → repository 흐름 유지
→ 복잡한 Domain Service, Application Service 분리는 없음
→ 엔티티도 JPA 엔티티 그대로 사용

그래서 구조는 다음처럼 됨:

src/main/java/com/example/server/domain/product
├── controller       (REST API)
├── service          (비즈니스 로직)
├── repository       (DB 접근)
├── entity           (도메인 모델)
└── dto              (요청/응답 DTO)

6. 왜 이 방식이 현실에서 많이 쓰이나?

장점

  • 도메인이 커져도 유지보수 쉬움
  • 프로젝트 규모 커져도 모듈별로 독립성 유지됨
  • DDD에 영감을 받은 구조라 도메인 이해가 쉽다
  • 개발 생산성 매우 높다
  • 복잡성은 낮고 관리성은 높다

단점

  • 정통 DDD만큼의 완전한 도메인 모델링은 어려움
  • 애그리게이트 설계 등 고급 기법 적용이 제한적

하지만 대부분의 프로젝트에서는 이 정도면 충분하고,
이 방식이 실무에서 가장 많이 쓰이는 “현실적인 DDD-lite” 구조다.


7. 한 줄로 요약

도메인별로 코드를 묶는(Domain-first 패키징) +
계층별 역할은 단순하게 유지하는(Layered service)
현실적인 소프트웨어 구조 방식.


profile
기술정리

0개의 댓글