> For the complete documentation index, see [llms.txt](https://wonjoon.gitbook.io/joons-til/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wonjoon.gitbook.io/joons-til/techtalk-review/woowacon/2024/ddd.-thats-not-how-you-do-it.md).

# DDD. That's not how you do it

[https://www.youtube.com/watch?v=sLG5n\_pXWK0\&ab\_channel=우아한테크](https://www.youtube.com/watch?v=sLG5n_pXWK0\&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC)

## 📌 DDD, 그거 그렇게 하는 거 아닌데 – 발표 정리

발표자: 박재성 (우아한형제들, 서버 개발자 / 우아한테크코스 모바일 캡틴)

### 🧭 발표 목적

* 도메인 주도 설계(DDD)를 잘못 이해하고 도입하려는 시도를 되짚어봄
* 그린필드/브라운필드 상황별 DDD 도입 실천 방안 제시
* 실제 팀 내 설계·협업 과정에서의 인사이트 공유

***

### 1️⃣ 도메인 주도 설계(DDD)란?

* **정의**: 도메인 모델의 적용 범위를 구현으로 확장하기 위해 도메인을 탐색하고 학습하기 위한 원칙과 패턴의 모음.
* **출처**: 에릭 에반스의 『Domain-Driven Design』 (2003)
* **중요 포인트**: 복잡성을 다루는 철학적 접근이 핵심이지, 특정 디자인 패턴만을 의미하지 않음.
* **기반 철학**: 객체지향(OOP), 애자일

***

### 2️⃣ 잘못된 DDD 도입 사례 (그린필드 기준)

#### 💥 문제적 문장 3가지

1. “`DDD` 하려면 **클린 아키텍처** or **헥사고날 아키텍처**를 써야 해요”
2. “**`서비스를 먼저 나눠서`** 마이크로서비스 아키텍처(MSA)를 시작할게요”
3. “**애그리거트, 도메인 이벤트**를 도입하려면 `완벽한 설계`가 필요해요”

#### 👉 공통된 문제:

* 구현부터 접근
* 용어만 강조하며 맥락이나 목적 없는 도입
* 팀 내 합의와 컨텍스트 없이 구조만 흉내냄

***

### 3️⃣ 그린필드에서의 DDD

#### 🧠 오스트랄로피테쿠스 패턴

> "들으면 어려워 보이는 생소한 용어만 먼저 도입하는 행태"

* 예: TDD, BDD, 자일 등 무작정 도입
* 해결: “문제가 뭔지 → 왜 이 방법이 유효한지” 먼저 대화하고, 기술은 도구로만 활용

#### 🔍 마이크로서비스 프리미엄

> “서비스 먼저 나누고 보자” → 오히려 복잡성만 증가

* 해결:
  * 초기에는 **모놀리식**으로 시작
  * `단일 패키지 → 점진적 리팩토링 → 모듈 분리 → 필요 시 MSA`
  * 핵심은 아키텍처보다 `올바른 **경계(바운디드 컨텍스트)**` 도출
    * 즉, 도메인 분석에 대한 시간을 가져야 함

#### 🧱 완벽한 설계는 없다

> 변화는 필연. 완벽한 설계를 고집하면 실행 불능

* 요구사항은 항상 변한다.
* 설계는 유연하고 자율성을 내포해야 함 → 변화 자체를 내재화하는 프로세스를 만든다. (애자일)
* ‘완벽’보다는 '점진적 개선' + '자기 설명 가능한 코드' 지향

***

### 4️⃣ 코드에서 시작하는 DDD

#### ⚙️ 게터/세터는 나쁘지 않다

* 초기에는 `getter/setter`도 괜찮음
* 점차적으로 `의미 있는 메서드`로 리팩토링 → 풍부한 도메인 모델

```java
// Before
car.setPosition(car.getPosition() + 1);
// After
car.move();
```

* OOP는 분명 DDD의 기반이지만, OOP는 DDD와 동일하지 않다.

#### 💬 유비쿼터스 언어

* 클래스나 함수의 이름을 짓기가 너무 어렵기에 도입
* 모든 팀원이 같은 용어를 공유해야 함 (디자이너/기획자 포함 프로젝트의 모든 곳에서 사용)
* 용어 사전은 **명사뿐 아니라 동사도 포함**
* README와 함께 **리비전 관리**하여 살아있는 문서로 유지(형상관리)
  * 용어사전

    <img src="https://github.com/user-attachments/assets/0e42910c-d681-4273-b3cf-3c2e96025cef" alt="Image" height="413" width="701">
  * 인수 테스트

    <img src="https://github.com/user-attachments/assets/b89e7348-6e1b-4dd1-8aab-85c8350e47d1" alt="Image" height="345" width="841">

    고객의 관점에서 소프트웨어가 어떻게 작동하는지를 고려한다.

***

### 5️⃣ 브라운필드에서의 DDD

* 브라운필드? → 출시 후 어제까지 작성한 코드가 있는 프로젝트

#### 🎯 비즈니스 도메인을 이해해야 하는 이유

* 개발자의 월급은 **비즈니스의 성공**에서 나온다
* 비즈니스 도메인 = 소프트웨어로 해결하고자 하는 문제 영역
* 비즈니스 = 사용자의 활동과 관심사
* 하위 도메인으로 분해: 상품, 전시, 결제, 정산 등

#### 🔍 도메인 분류 기준

* 어디서, 어떻게 돈을 벌 것인가? 우리의 비전은 무엇인가?
* 코어 / 서포팅 / 제너릭 (ex. 코어 = 주문, 제너릭 = 이메일 전송)
* 아래는 core domain chart

  <img src="https://github.com/user-attachments/assets/58efa3f6-9fd0-4fd7-b7fd-957784414a04" alt="Image" height="463" width="561">
* 팀 역량/자원 배분도 이에 따라 조정

#### 📊 활용 도구

* 이벤트 스토밍, 도메인 스토리텔링, 컨텍스트 매핑 등 시각화 도구 활용

***

### 이제 비즈니스 문제를 어떻게 해결해야할 지 고민

### 6️⃣ 경계를 나누는 기준

#### ✂️ 바운디드 컨텍스트 나누기(문제를 해결하기 위해 범위를 좁혀야 함)

* 바운디드 컨텍스트 = 복잡한 도메인을 명확하게 분리된 영역으로 나누는 단위
* 같은 용어라도 다른 의미로 쓰일 때 (ex. ‘과제’ vs ‘과제 제출물’)
* 외부 시스템 격리 등 개발자 의견
* 모두가 다르게 생각할 수 있음을 인정하고, **함께 그림 그려보기**

> 시작은 단순하게, 점진적 분리 → “작고 중요한 것부터” (작은 문제를 하나씩 해결)

***

### 7️⃣ 외부와 단절하는 3가지 패턴

* 외부 시스템과 통합하다보면 용어나 로직이 오염됨. (예: userId ↔ memberId)

1. **DTO**: 외부 데이터 수용을 위한 구조체
2. **DIP**: 의존성 역전
3. **ACL (Anti-Corruption Layer)**:
   * 외부 시스템의 모델/용어가 내부로 침범하지 않도록 차단
   * 번역 계층, Adapter 계층 등으로 구현
   * 외부 시스템을 쉽게 교체하는 장점을 얻을 수 있음

***

### 8️⃣ 자연스러운 아키텍처 형성

* DTO, DIP, ACL을 적용하다보면 자연스럽게 아키텍처가 그려짐
* 핵사고날/클린 아키텍처는 **결과물**이지 **목표**가 아님
  * 핵사고날: 시스템을 중심에 두고, 포트와 어댑터를 통해 외부와 소통한다. (호환성 높임)
  * 클린: 외부 기술은 언제든 교체될 수 있어야 한다. (구현체만 갈아끼움)
* 처음부터 도입하지 말고, 필요에 따라 **진화시켜 나가기**
* 구현 → 점진적 리팩토링 → 아키텍처 도출

***

### 9️⃣ 조직 내 확산 전략

* **변화를 유도할 사람**이 필요(동맹)
* 호기심 유발 (ex. 화이트보드 낙서)
  * 실제 발표자의 화이트보드

    <img src="https://github.com/user-attachments/assets/dc38c75b-3393-441b-8da5-596576b66cb1" alt="Image" width="563">
* Issue 발급 → 자연스러운 논의 유도 → 동료 설득

***

### 1️⃣0️⃣ 마무리 메시지

* DDD는 도구가 아니라 **철학**
* "우리에게 왜 필요한가?"라는 질문부터 시작하라
* 개발을 잘하는 것이 아니라, **프로젝트를 잘하는 방법**이다
* 프로젝트에 도움이 되는 DDD 아이디어를 필터링 하여 적용

***

### 📚 추천 도서

* 『소프트웨어 장인』
* 『팀 토폴로지』
* 『소프트웨어 아키텍처 101』

***

### 🎯 발표에서 주목해야 할 핵심 포인트 (What to Focus On)

| 핵심 메시지             | 설명                                            | 왜 중요한가                        |
| ------------------ | --------------------------------------------- | ----------------------------- |
| 기술보다 문제 정의가 먼저다    | “DDD 하자”는 말보다, \*\*왜 필요한가?\*\*를 먼저 설명해야 한다    | 기술 도입의 본질은 문제 해결이다            |
| 아키텍처는 진화시켜야 한다     | 처음부터 클린/헥사고날 아키텍처를 적용하지 말고, 구현하며 점진적으로 리팩토링하라 | 실무에서 처음부터 완벽한 구조를 잡는 건 환상이다   |
| 완벽한 설계는 없다         | 요구사항은 계속 바뀌므로 “완벽한 설계”를 추구하면 실행 자체가 안 됨       | 설계보다 변화 대응 능력이 중요             |
| 용어 정리는 진짜 중요하다     | 유비쿼터스 언어와 용어 사전은 협업 효율과 도메인 이해에 필수            | 코드를 명확하게 설명할 수 있어야 유지보수가 쉬워진다 |
| 바운디드 컨텍스트는 구체적 경계다 | 같은 단어라도 문맥이 다르면 컨텍스트를 나눠야 한다                  | 설계 충돌을 방지하고 팀 간 협업을 원활히 만든다   |

### 느낀점

DDD에 대해 막연하게만 알고 있었는데, 이번 발표를 통해 도메인 중심의 사고방식이 왜 중요한지를 알게 되었습니다.

* ‘완벽한 설계는 존재하지 않는다’는 메시지와, 바운디드 컨텍스트를 함께 그려보자는 제안이 인상 깊었습니다.
* ‘외부와 단절하기 위한 3가지 패턴’, ‘어떻게 용어를 정리하고 점진적으로 나누는지’ 등의 구체적인 방법들이 큰 도움이 되었습니다.
