DDD. That's not how you do it

https://www.youtube.com/watch?v=sLG5n_pXWK0&ab_channel=우아한테크

📌 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도 괜찮음

  • 점차적으로 의미 있는 메서드로 리팩토링 → 풍부한 도메인 모델

// Before
car.setPosition(car.getPosition() + 1);
// After
car.move();
  • OOP는 분명 DDD의 기반이지만, OOP는 DDD와 동일하지 않다.

💬 유비쿼터스 언어

  • 클래스나 함수의 이름을 짓기가 너무 어렵기에 도입

  • 모든 팀원이 같은 용어를 공유해야 함 (디자이너/기획자 포함 프로젝트의 모든 곳에서 사용)

  • 용어 사전은 명사뿐 아니라 동사도 포함

  • README와 함께 리비전 관리하여 살아있는 문서로 유지(형상관리)

    • 용어사전

      Image
    • 인수 테스트

      Image

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


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

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

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

  • 개발자의 월급은 비즈니스의 성공에서 나온다

  • 비즈니스 도메인 = 소프트웨어로 해결하고자 하는 문제 영역

  • 비즈니스 = 사용자의 활동과 관심사

  • 하위 도메인으로 분해: 상품, 전시, 결제, 정산 등

🔍 도메인 분류 기준

  • 어디서, 어떻게 돈을 벌 것인가? 우리의 비전은 무엇인가?

  • 코어 / 서포팅 / 제너릭 (ex. 코어 = 주문, 제너릭 = 이메일 전송)

  • 아래는 core domain chart

    Image
  • 팀 역량/자원 배분도 이에 따라 조정

📊 활용 도구

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


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

6️⃣ 경계를 나누는 기준

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

  • 바운디드 컨텍스트 = 복잡한 도메인을 명확하게 분리된 영역으로 나누는 단위

  • 같은 용어라도 다른 의미로 쓰일 때 (ex. ‘과제’ vs ‘과제 제출물’)

  • 외부 시스템 격리 등 개발자 의견

  • 모두가 다르게 생각할 수 있음을 인정하고, 함께 그림 그려보기

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


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

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

  1. DTO: 외부 데이터 수용을 위한 구조체

  2. DIP: 의존성 역전

  3. ACL (Anti-Corruption Layer):

    • 외부 시스템의 모델/용어가 내부로 침범하지 않도록 차단

    • 번역 계층, Adapter 계층 등으로 구현

    • 외부 시스템을 쉽게 교체하는 장점을 얻을 수 있음


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

  • DTO, DIP, ACL을 적용하다보면 자연스럽게 아키텍처가 그려짐

  • 핵사고날/클린 아키텍처는 결과물이지 목표가 아님

    • 핵사고날: 시스템을 중심에 두고, 포트와 어댑터를 통해 외부와 소통한다. (호환성 높임)

    • 클린: 외부 기술은 언제든 교체될 수 있어야 한다. (구현체만 갈아끼움)

  • 처음부터 도입하지 말고, 필요에 따라 진화시켜 나가기

  • 구현 → 점진적 리팩토링 → 아키텍처 도출


9️⃣ 조직 내 확산 전략

  • 변화를 유도할 사람이 필요(동맹)

  • 호기심 유발 (ex. 화이트보드 낙서)

    • 실제 발표자의 화이트보드

      Image
  • Issue 발급 → 자연스러운 논의 유도 → 동료 설득


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

  • DDD는 도구가 아니라 철학

  • "우리에게 왜 필요한가?"라는 질문부터 시작하라

  • 개발을 잘하는 것이 아니라, 프로젝트를 잘하는 방법이다

  • 프로젝트에 도움이 되는 DDD 아이디어를 필터링 하여 적용


📚 추천 도서

  • 『소프트웨어 장인』

  • 『팀 토폴로지』

  • 『소프트웨어 아키텍처 101』


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

핵심 메시지
설명
왜 중요한가

기술보다 문제 정의가 먼저다

“DDD 하자”는 말보다, **왜 필요한가?**를 먼저 설명해야 한다

기술 도입의 본질은 문제 해결이다

아키텍처는 진화시켜야 한다

처음부터 클린/헥사고날 아키텍처를 적용하지 말고, 구현하며 점진적으로 리팩토링하라

실무에서 처음부터 완벽한 구조를 잡는 건 환상이다

완벽한 설계는 없다

요구사항은 계속 바뀌므로 “완벽한 설계”를 추구하면 실행 자체가 안 됨

설계보다 변화 대응 능력이 중요

용어 정리는 진짜 중요하다

유비쿼터스 언어와 용어 사전은 협업 효율과 도메인 이해에 필수

코드를 명확하게 설명할 수 있어야 유지보수가 쉬워진다

바운디드 컨텍스트는 구체적 경계다

같은 단어라도 문맥이 다르면 컨텍스트를 나눠야 한다

설계 충돌을 방지하고 팀 간 협업을 원활히 만든다

느낀점

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

  • ‘완벽한 설계는 존재하지 않는다’는 메시지와, 바운디드 컨텍스트를 함께 그려보자는 제안이 인상 깊었습니다.

  • ‘외부와 단절하기 위한 3가지 패턴’, ‘어떻게 용어를 정리하고 점진적으로 나누는지’ 등의 구체적인 방법들이 큰 도움이 되었습니다.

Last updated