DDD 그거 그렇게 하는 거 아닌데 #우아콘2024 #우아한형제들
ORIGINAL SOURCE ↗YouTube에서 보기 | 영상 길이: 42분 16초
요약
발표자 소개 및 발표 배경
발표자는 우아한형제들 소속 8년차 서버 개발자 박재성으로, 우아한테크코스에서 코틀린 강의를 담당하고 있다. 7년간 도메인 주도 설계(DDD)를 독학하고 팀에 전파하면서 쌓은 경험을 공유하는 자리다.
DDD는 에릭 에반스가 2003년에 쓴 동명의 책에서 유래한 방법론이자 철학이다. 발표자는 “도메인 주도 설계”라는 제목보다 책의 부제인 “소프트웨어의 복잡성을 다룬 지혜” 를 더 좋아한다고 말한다. “도메인 주도 설계”라는 표현은 구현 방식에 포커스가 맞춰지는 반면, 부제는 개발 외의 방법으로도 문제를 해결할 수 있다는 넓은 시야를 준다는 이유에서다. DDD의 개념적 기반은 객체지향 프로그래밍과 애자일이며, 2024년 기준으로 읽으면 “당연한 이야기”와 “올드해서 읽기 힘든 이야기”가 섞여 있다.
발표 대상은 “가랑비 오자듯 조용히 DDD를 팀에 도입하고 싶은 분”이다. 즉, 무턱대고 DDD를 외치기보다 자연스럽게 녹여내고 싶은 실무자를 위한 발표다.
흔한 오해 1: “DDD를 하려면 헥사곤/클린 아키텍처를 먼저 써야 한다” — 오스트랄로피테쿠스 패턴
발표자는 낯선 기술 용어를 상대방이 아무 맥락도 없는 상태에서 꺼낼 때 발생하는 거부 반응을 오스트랄로피테쿠스 패턴이라 명명한다. 예를 들어 동료가 갑자기 “이번 프로젝트에서 오스트랄로피테쿠스 아프리카누스를 도입할 예정이에요”라고 한다면 처음 듣는 사람은 즉각적으로 배타적 반응을 보인다. 이는 인류의 생존 본능, 즉 DNA에 새겨진 방어 기제다. TDD, BDD, ATDD, 애자일 같은 용어도 준비되지 않은 상대에게 무턱대고 꺼내면 이 패턴에 해당된다.
해결책: 문제를 먼저 정의하고, 그 문제를 해결하기 위한 기술적 수단을 논의한다. 팀원이 야근으로 지쳐있는 상황에서 “우리 이제 DDD 합시다”라고 접근하면 반발만 생긴다. 현재 팀의 상태와 직면한 문제를 먼저 파악하는 것이 우선이다.
흔한 오해 2: “MSA를 도입하기 위해 일단 서비스를 나누고 시작하자” — 마이크로서비스 프리미엄
많은 MSA 관련 서적들이 DDD의 바운디드 컨텍스트를 기준으로 서비스를 나눈다고 설명한다. 이 때문에 DDD를 처음 접하게 되는 계기가 MSA 공부에서 비롯되는 경우도 많다. 그러나 성급한 서비스 분리는 마이크로서비스 프리미엄이라는 부작용을 낳는다.
서비스를 일찍 물리적으로 분리하면 데이터베이스 등 인프라도 모두 쪼개지고, 서비스 간 결합도가 높아져 난감한 상황이 반복된다. 헥사곤 아키텍처, 클린 아키텍처도 마찬가지로, 도메인 이해 없이 패키지 구조부터 잡으면 복잡성만 증가한다.
해결책: 일단 모놀리식(단일 패키지)으로 시작한다. “다 때려 박고 시작”한 뒤, 패키지를 나누고, 모듈을 분리하고, 어느 정도 운영 경험이 쌓이면 그때 MSA 도입을 고민한다. 중요한 것은 먼저 올바른 바운디드 컨텍스트를 찾는 노력, 즉 우리 도메인이 어떤 도메인인지 분석하는 시간이다.
흔한 오해 3: “애그리거트/도메인 이벤트를 도입하려면 완벽한 설계가 필요하다”
완벽한 설계는 존재하지 않는다. 아키텍처 의사결정을 내리는 것은 결국 사람이고, 주관과 판단이 개입한다. 소프트웨어(software)라는 이름 자체가 “말랑말랑함”을 내포하고, 요구사항은 끊임없이 변한다. 기획자도 모든 요구사항을 처음부터 완전히 파악하지 못한다.
해결책: 완벽한 설계가 없다는 것을 인정하고, 변화에 맞서 싸우기보다 변화를 내재하는 프로세스(애자일) 를 만드는 것이 중요하다. 이것이 DDD의 근간인 애자일과 닿아 있는 부분이다.
그린필드: 게터/세터로 시작해 점진적으로 리팩토링하라
그린필드(아무것도 없는 상태로 시작하는 프로젝트)에서 DDD를 적용하는 현실적인 방법을 코드 예시로 설명한다.
처음에는 도메인 클래스(예: Car)의 역할과 책임을 전혀 모르는 상태다. 이때 게터/세터를 먼저 노출해두고 개발을 시작한다. 게터/세터가 무조건 나쁜 것이 아니라, 초기에 도메인 지식이 없을 때 빠르게 구현을 시작하는 데 큰 도움이 된다.
개발을 진행하며 getPosition() 후 setPosition() 패턴이 반복되는 것이 보이면, 이를 move() 메서드 하나로 추출할 수 있다. 이런 식으로 객체에게 메시지를 던지는 방식으로 리팩토링을 반복하다 보면, 게터/세터만 존재하던 빈약한 도메인 모델이 풍부한 도메인 모델로 진화한다. 예컨대 DEFAULT_POSITION = 0이라는 상수가 자연스럽게 등장하고, 코드만 봐도 “자동차의 초기 위치는 0이다”라는 비즈니스 규칙을 읽을 수 있게 된다.
[16:41] Car 클래스에 move() 메서드를 구현했다고 “DDD를 했나요?”라는 질문에 발표자는 “DDD 기반인 것은 맞지만 DDD와 동일하지 않다”고 답한다. DDD는 코드 패턴 하나가 아니라 더 넓은 개념이다.
그린필드: 유비쿼터스 언어 — 팀 전체가 쓰는 공통 용어
도메인 모델을 리팩토링하다 보면 가장 어려운 순간이 온다: 네이밍. 이때 유비쿼터스 언어(Ubiquitous Language) 를 도입한다. “유비쿼터스”는 “언제 어디서나”라는 의미의 형용사로, 회의·기획·디자인·개발 등 프로젝트의 모든 곳에서 동일하게 사용하는 언어다.
개발자 혼자 영문 이름을 고민하지 않아도 된다. 기획자와 디자이너도 영문 이름을 고민하는 만큼, 이 작업은 함께 해야 한다. 그린필드 단계에서는 바운디드 컨텍스트가 아직 없으므로, 굳이 컨텍스트 내부에 용어를 정의하려 하지 않아도 된다.
용어 사전 관리법: 발표팀은 별도 위키 대신 README 파일로 소스코드와 함께 형상관리한다. 덕분에 용어도 코드 리뷰 대상이 되고, 더 의미 있는 용어를 지속적으로 발굴한다. 용어 사전에는 명사뿐 아니라 동사(행위) 도 반드시 포함해야 한다. 예: move, brake 등.
실제 사례로, 우아한테크코스에서 “과제”라는 단어가 교육팀(내어 주는 것)과 학생(제출하는 것)에게 서로 다른 의미로 쓰이는 혼선이 있었다. 이를 해결하기 위해 “과제”(교육팀이 내는 것)와 “과제 제출물”(학생이 제출하는 것)로 한글 명칭까지 명시적으로 분리했다.
인수 테스트와의 연계: 용어가 정의되면 이를 활용해 인수 조건을 작성할 수 있고, 반대로 인수 테스트를 작성하는 과정에서 자연스럽게 용어에 대한 논쟁과 논의가 발생해 더 풍부한 용어가 발굴된다. 양방향으로 시너지가 생긴다.
브라운필드: 개발자도 비즈니스 도메인을 알아야 한다
브라운필드는 이미 출시된, 어제까지 작성한 코드가 있는 프로젝트다. 흔한 오해: “개발자는 비즈니스 도메인을 몰라도 된다.” 발표자는 단호하게 반박한다. “여러분의 월급은 비즈니스에서 나온다. 비즈니스가 잘돼야 성과금도 나온다.”
비즈니스 도메인이란 소프트웨어가 해결하고자 하는 문제 영역, 사용자의 활동·관심사와 관련된 공간이다. 소프트웨어 산업의 특이점은 전자상거래, 자동차, 딜리버리 등 다른 산업의 비즈니스 문제를 해결한다는 점이다. 개발자는 운영자가 아니지만, 개발하고 있는 것에 대한 도메인 지식을 갖추고 있어야 개발이 가능하다.
도메인 지식 습득 방법:
- 우리가 어떤 비즈니스를 하는지 면밀히 파악한다.
- 선두 업체 또는 경쟁사가 어떤 기능을 제공하는지 분석한다. (발표자는 광고 플랫폼 개발 당시 구글·메타의 광고 상품 구조를 미리 파악해 확장 방향을 예측했다.)
- “어디까지 확장에 열어둬야 하나”라는 고민에 경쟁사 분석이 좋은 기준이 된다.
브라운필드: 하이 도메인과 코어 도메인 차트
전자상거래라는 큰 도메인은 하이 도메인으로 쪼개진다: 상품, 전시, 주문, 결제, 정산 등. 일부는 외부 시스템(결제 서비스, 로그인 서비스)으로 처리하기도 한다.
한정된 자원(인력, 시간)을 어디에 집중할지 결정하기 위해 코어 도메인 차트를 활용한다. 각 하이 도메인을 다음 세 가지로 분류한다:
- 핵심 도메인 (Core): 경쟁 우위를 만드는 영역
- 지원 도메인 (Supporting): 핵심을 뒷받침하는 영역
- 일반 도메인 (Generic): 메일, 메시지 전송 등 범용적인 영역
이를 통해 “갓 개발자를 어디에 붙일지, 신입 개발자를 어디 배치할지”를 결정한다. 핵심 도메인은 시장 상황, 회사 비전, 새 사업 발굴, 예상 못한 고객 행동에 따라 변한다.
시각화 도구: 이벤트 스토밍(발표자가 전년도 우아콘에서 발표), 도메인 스토리텔링(최근 한국어 번역 출판) 등을 활용해 비즈니스 지식의 이해도를 팀 전체가 검토하고 발전시킨다.
브라운필드: 바운디드 컨텍스트 나누기 — 점진적으로
[34:30] 문제를 해결하려면 범위를 좁혀야 한다. 즉, 분할과 정복이다. (고대 로마 제국도 중앙에서 멀리 떨어진 도시를 통제하기 위해 같은 전략을 썼다.) 여러 개의 작은 바운디드 컨텍스트로 나누는 기준은 두 가지다:
- 같은 용어가 다른 의미를 갖거나, 같은 대상을 다르게 지칭하는 경우 — “과제” 사례처럼. 용어를 바꾸기 애매하다면 경계를 그어서 컨텍스트 내부에서만 정의한다.
- 외부 시스템의 도입 경계 — 외부 시스템을 어떻게 격리할지는 개발자 의견이 중요하다.
팀원마다 바운디드 컨텍스트에 대한 생각이 다르다. 발표자가 추천하는 방법: 팀원 각자가 바운디드 컨텍스트를 따로 그려보고, 그린 것을 토대로 논의를 시작한다. 처음부터 모두 나누는 “빅뱅” 방식이 아니라, 가장 작거나 영향력이 적거나 가장 중요한 것부터 하나씩 점진적으로 분리한다.
외부 세계와의 단절: DTO, DIP, ACL
외부 시스템이 우리 비즈니스에 역으로 간섭하지 못하도록 막는 세 가지 패턴:
- DTO (Data Transfer Object): 외부와의 데이터 교환 전용 객체
- DIP (Dependency Inversion Principle): 의존성 역전으로 외부 시스템에 종속되지 않음
- ACL (Anti-Corruption Layer, 부패방지계층): 외부 시스템의 용어·모델이 우리 시스템 내부로 침투하지 못하게 번역하는 계층. 물리적으로 별도의 레이어일 필요는 없고, 외부 API 호출 코드 내에서 우리 언어로 번역하는 메서드 하나만 있어도 ACL로서 역할을 한다.
[38:00] 처음에 단일 패키지로 시작해 레이어드 아키텍처(3-tier)를 선택하고, 여기에 DTO·DIP·ACL을 적용하다 보면 자연스럽게 도메인이 주도하는 아키텍처가 완성된다. 처음부터 클린 아키텍처·헥사곤 아키텍처를 패키지 구조로 잡는 것보다, 구현하고 리팩토링하다 보면 그 형태가 스스로 만들어진다는 것이 발표자의 핵심 주장이다.
참고로 에릭 에반스의 원서는 레이어드 아키텍처를, 반 버논의 책은 헥사곤 아키텍처를, 최근 DDD 관련 서적들은 클린 아키텍처를 설명한다. 시대에 따라 권장 아키텍처가 달라질 뿐이다.
조직간 협업과 전략적 설계
브라운필드 환경에서는 이미 팀이 분리되어 있고, 시스템 아키텍처는 조직 구조를 따라가고 있다 (콘웨이의 법칙). 조직 간 협업 방식 — API 설계 시 함께 논의하기, 한 조직이 일방적으로 결정하기, 강력한 중앙 통제 등 — 이 모두 DDD에서 말하는 전략적 설계에 해당한다. 발표 내내 다룬 내용이 전부 DDD였다.
DDD 도입 전략: “DDD를 합시다”로 시작하지 마라
발표자가 실제로 활용한 호기심 유발 전략: 바운디드 컨텍스트 논의를 시작하기 한 달 전, 사람들이 자주 오가는 길목의 화이트보드에 그림을 그려뒀다. 지나가던 동료가 “이게 뭐예요?”라고 물어봐도 바로 설명하지 않았다. 한 달 뒤 “우리 바운디드 컨텍스트 한번 도출해 봐요”라는 이슈를 등록하고, 미리 그려둔 그림을 기반으로 자연스럽게 논의가 열렸다.
DDD 도입의 핵심 원칙:
- 변화가 일어나도록 도와줄 사람(동맹)을 구축한다.
- 호기심을 유발하는 다양한 마케팅 기법을 활용한다.
- DDD는 “DDD를 합시다”로 시작하지 않는다. 왜 필요한지를 하나씩 도입하다 보면 “하고 보니까 DDD네”라는 경험을 하게 된다.
- DDD는 개발만 잘하는 것이 아니라 프로젝트 전체를 잘하는 방법이다.
마무리: 은총알은 없다
“은총알은 없다(No Silver Bullet)” — 브룩스의 유명한 논문 제목처럼, 소프트웨어 개발에는 단일한 해답이 없다. 핵심은:
- 비즈니스를 이해하고 관련 지식을 쌓는다.
- 본질적 복잡성(문제 자체의 어려움)과 우발적 복잡성(불필요한 기술적 오버헤드)을 구별한다.
- 소프트웨어 개발은 개발자만의 일이 아니다. 프로젝트 참여자 전체가 함께 도메인을 이해해야 한다.
추천도서 (DDD 책 없음!):
- 소프트웨어 장인
- 팀 토폴로지
- 소프트웨어 아키텍처 101
키워드
DDD, 도메인주도설계, 바운디드컨텍스트, 유비쿼터스언어, 그린필드, 브라운필드, MSA, 헥사곤아키텍처, ACL, 부패방지계층, 점진적리팩토링, 전략적설계, 코어도메인, 우아콘2024