지난 편에서 도메인 주도 설계가 무엇인지를 살펴봤어요. 이번 편에서는 DDD의 핵심인 도메인 모델(Domain Model)이 무엇이고, 좋은 도메인 모델의 기준은 무엇인지, 그리고 프로덕트 관리가 도메인 모델링에서 어떤 역할을 하는지를 구체적으로 알아볼게요.
“도메인 모델”이라는 말을 처음 들으면, 다음과 같은 ‘산출물’을 떠올려요.
- 상자와 화살표로 이루어진 다이어그램
- UML 차트
- 코드 속 클래스 집합
이런 것들이 실무에서 유용할 수는 있지만, 도메인 모델 그 자체는 아니에요. 도메인 모델의 표현 방식일 뿐이죠.
1. 도메인 모델이란 무엇인가 (그리고 무엇이 아닌가)
도메인 모델(Domain Model)은 사용자 활동에 대한 지식을 구조화하여 표현하는 방식이에요.
좀 더 구체적으로 말하면 다음과 같아요.
- 사용자의 세계에 무엇이 존재하는지에 대한 공유된 이해
- 그것들이 서로 어떻게 관련되는지
- 어떤 규칙이 그 행동을 지배하는지
도메인 모델은 사용자의 맥락을 추상화(Abstraction)하는 것이지, 구체화 하는 것(Specification)이 아니에요.
워크숍 기획을 도와주는 제품을 생각해 보세요. 사용자들은 이런 것들을 이야기할 거예요.
- 워크숍 세션
- 워크숍 진행자
- 시간대
- 안건
- 참가자
- 방 수용 인원이나 세션 겹침 같은 제약사항들
도메인 모델은 이 복잡한 현실을 다음과 같은 고민들을 통해 추상화하여 일관된 개념 체계로 바꿔요.
- 세션이란 무엇이고, 유효한 세션의 조건은 무엇인가?
- 진행자가 동시에 두 세션을 진행할 수 있는지?
- 안건은 확정된 계획인지, 수정 가능한 것인지?
- 참가자가 “확정”으로 바뀌는 시점은 언제인지?
여기까지는 UI 결정이나 데이터베이스 테이블이 필요하지 않아요. 하지만 이 질문들에 답하지 않으면, 구현 결과물은 추측에 기반할 수밖에 없게 되죠.
도메인 모델을 비유하면, 보드게임의 규칙서와 같아요. 체스를 둘 때 “킹은 한 칸만 이동, 퀸은 어느 방향이든 무제한 이동”이라는 규칙이 명확해야 게임을 할 수 있죠. 규칙서 없이 “대충 알아서 두자”고 하면, 참가자마다 다른 규칙으로 게임하게 돼요. 도메인 모델도 제품의 핵심 개념과 규칙을 명확히 정의한 규칙서인 셈이에요.
2. 도메인 모델 vs 다이어그램 vs 코드: 진짜 모델은 어디에 있는가
종종 어떤 팀은 다이어그램, 코드와 같은 산출물 자체가 제품에 대한 이해를 보여주는 도메인 모델 그 자체라고 주장해요.
하지만
- 다이어그램은 현재 도메인을 이해하는 방식 중의 하나인 스냅샷이에요
- 코드는 그 이해의 구체적 표현이에요
- 도메인 모델은 다이어그램과 코드보다 더 기반이 되는 것이며, 계속 진화해요
그래서 아름답게 그려진 다이어그램이 있어도 사용자와 개발자에게 혼란스러운 제품을 출시하는 팀이 있는 거예요. 모델 자체가 의도한 목표를 제대로 정의하지 않았기 때문이죠.
도메인 모델은 “제품의 개념적 뼈대”와 같은 거예요. 문서 산출물이 아니라요.
건물의 설계 의도와 도면·실제 건물의 관계와 같아요. 건축가가 “자연광이 충분히 들어오고, 동선이 효율적인 사무실”이라는 설계 의도(도메인 모델)를 갖고 있어요. 도면(다이어그램)은 그 의도를 평면에 표현한 것이고, 건물(코드)은 실제 구현이에요. 도면이 예쁘더라도 설계 의도 자체가 잘못되면, 결국 불편한 건물이 나오죠.
3. 도메인 관계: 방향성, 한정자, 불필요한 연결 제거
도메인 모델에서 개념들 사이의 관계를 다룰 때, 세 가지 원칙이 중요해요.
1) 방향을 부여하기
기본적으로 단방향 관계에 기반해요. 한 객체가 다른 객체를 알지만, 반대쪽은 몰라도 되는 거죠. 이렇게 하면 개념적 결합도가 줄어들고, 소유권과 변경 영향 관계가 더 명확해져요.
2) 한정자(Qualifier) 사용하기
한정자는 날짜, 역할, 상태 같은 맥락을 추가해서 일대다로 커질 수 있는 관계를 좁히는 역할을 해요. 모호한 관계가 정밀한 도메인 규칙과 접근 패턴으로 바뀌죠.
3) 필수적이지 않은 관계는 제거하기
행동이나 의사결정에 필요하지 않은 직접 연결을 제거해요. 도메인 모델이 작고 유연하며 확장하기 쉬워지죠.
이 세 가지 원칙은 모두 같은 목표를 향해요. 도메인 모델이 성장해도 이해하기 쉽게 유지하는 것이에요. 더 많은 구조를 추가하는 대신, 의도적으로 관계를 제거하거나 제한해서 행동에 핵심적인 연결 관계만 남기는 거죠.
도메인 관계 원칙을 비유하면, 조직도 정리와 같아요. 모든 부서가 서로 직접 소통하면 혼란스럽지만, “마케팅팀은 영업팀에 리드를 전달하고, 영업팀은 CS팀에 고객 정보를 전달한다”처럼 방향을 정하면 흐름이 명확해져요. 불필요한 연결을 끊고, 필요한 곳에만 맥락(한정자)을 추가하면 조직이 커져도 소통이 원활하죠.
4. 좋은 도메인 모델의 기준: 설명 가능성, 협업, 반복
도메인 모델은 공동의 이해와 의사결정을 얼마나 잘 이끌어 내는지로 판단해야 해요. 좋은 도메인 모델은 세 가지 특성이 있어요.
1) 이름만 붙이는 게 아니라, 이름에 담긴 개념을 설명할 수 있어야 한다
이름을 붙이는 건 쉬워요. 설명하는 건 어렵죠.
예를 들어, 약한 도메인 모델은 이렇게 말해요.
- “세션(Session) 객체가 있다.”
더 강한 모델은 제품에서 세션이 실제로 무엇을 의미하는지 설명할 수 있어요.
워크숍 일정 관리 제품에서 좋은 도메인 모델을 가졌다면 다음과 같은 것들을 명확히 설명할 수 있어요.
- 세션이 언제 시작되고 끝나는지 → 세션은 퍼실리테이터가 참여할 때 시작돼요. 누군가가 캘린더에 만들기만 한다고 시작되는 게 아니에요.
- 세션 시작 전에 팀이 어떤 변경을 할 수 있는지 → 팀은 세션 시작 전에 시간과 퍼실리테이터를 변경할 수 있어요. 세션이 진행 중이면 변경할 수 없죠.
- 시스템이 성장해도 항상 유지되어야 하는 규칙 → 퍼실리테이터는 미래에 어떤 기능이 추가되더라도, 겹치는 세션을 절대 진행할 수 없어요.
팀원마다 세션이 무엇인지에 대해 다른 설명을 한다면, 모델이 아직 준비되지 않은 거예요.
2) 개별적 수집이 아닌 협업으로 만들어진다
좋은 도메인 모델은 한 사람이 “요구사항을 수집”해서 나오는 게 아니에요. 다음과 같은 과정을 거쳐야 하죠.
- 도메인 전문가가 자신의 사고 과정과 행동 방식을 설명한다
- 프로덕트 매니저가 “왜”와 “만약에”를 묻는 구체화 질문을 한다
- 개발자가 엣지 케이스와 제약 사항들에 대해 적극적으로 검증한다
이런 주고 받는 과정이 모든 사람의 사고를 정제하도록 강제해요. 도메인 전문가도 정확히 설명하려 할 때 비로소 자신의 가정을 인식하게 되는 경우가 많아요.
3) 일회성이 아닌 반복을 통해 진화해야 한다
약한 도메인 모델은 실제 현실을 마주하면 견디지 못해요. 좋은 도메인 모델은 보통 작지만 탄탄한 핵심을 기반으로 시작해요. 도메인 전문가 및 사용자와의 깊은 대화를 통해 만들어지죠.
- 실제 사용자 작업에 근거한 몇 가지 핵심 개념
- 책임의 명확한 소유권
- 비즈니스가 실제로 운영되는 방식을 반영하는 명시적 규칙
팀은 실제 제품 결정에 대입하면서 모델을 진화시켜요. 전형적인 사이클은 이런 모습이에요.
- 도메인 전문가 및 사용자와 긴밀히 협업하여 핵심 개념과 규칙의 작은 집합을 정의한다
- 실제 기능과 설계 논의에서 사용해 본다
- 설명이 무너지거나 억지스러워지는 지점을 관찰한다
- 언어, 경계, 책임을 정제한다
- 원래의 핵심을 잃지 않으면서 반복한다
여기서 반복은 끊임없는 재작업이 아니에요. 초기 가정을 실제 사용 상황에서 테스트하는 것이에요. 목표는 모든 것을 미리 예측하는 게 아니라, 제품이 진화해도 명확성을 잃지 않고 변화를 흡수할 수 있는 모델을 만드는 것이죠.
5. 도메인 모델을 만드는 과정에서 프로덕트 관리의 역할
1) 범위가 아닌 구조를 드러내는 PRD 작성
프로덕트 관리는 코드를 작성하지 않아도 도메인 모델에 독특한 방식으로 영향을 줄 수 있어요. 세 가지 실무적 접점이 있죠.
- 핵심 용어를 명시적으로 정의한다
- 어떤 규칙이 엄격하고 어떤 규칙이 유연한지 명확히 한다
- 불변 조건(항상 참이어야 하는 것)을 명시화한다
예를 들면 이런 거예요.
- “세션이 시작되면, 팀은 확정된 참가자를 유지한다.”
- “발행 전까지, 팀은 아젠다를 자유롭게 변경할 수 있다.”
기술적 아키텍처 결정을 결정 할 때, 이런 문장이 긴 기능 목록보다 더 효과적이에요.
2) 이해관계자 커뮤니케이션
이해관계자가 의견이 다를 때, 그 불일치는 종종 우선순위가 아니라 멘탈 모델에 대한 것이에요.
도메인 언어를 사용하면 이런 질문을 할 수 있어요.
- “우리가 행동에 대해 의견이 다른 건가요, 아니면 정의에 대해 의견이 다른 건가요?”
- “이 규칙이 모든 ‘세션’에 적용되나요, 아니면 ‘내부 워크숍’에만 적용되나요?” (워크숍 제품 예시)
이렇게 하면 대화가 의견 충돌에서 구조적 논의로 전환돼요. 여기서 프로덕트 매니저는 사용자 현실과 시스템 현실 사이의 통역사 역할을 하죠. 도메인 모델을 만드는 과정은 그 통역이 명시적으로 이루어지는 지점이에요.
6. 예시: 사내 회의실 예약 제품 도메인 모델
사내 팀 회의실 예약 제품을 상상해 보세요.
핵심 도메인 개념은 이런 것들이에요.
- 회의실(Room)
- 예약(Booking)
- 시간 슬롯(Time Slot)
- 주최자(Organizer)
도메인 모델이 답할 수 있는 초기 질문들이에요.
- 예약(Booking)이 회의실(Room)과 시간 슬롯(Time Slot) 둘 다 필요한지, 아니면 회의실 배정 전에도 존재할 수 있는지?
- 같은 주최자(Organizer)가 다른 회의실에서 겹치는 예약을 만들 수 있는지?
- 시간 슬롯(Time Slot)이 단순한 시작·종료 시간인지, 반복 규칙도 포함하는지?
이 도메인 모델을 통해 도출될 수 있는 규칙은 다음과 같아요.
- 예약(Booking)은 유효한 시간 슬롯(Time Slot) 없이는 유효하지 않다
- 시간 슬롯(Time Slot)은 시작 시간이 종료 시간보다 이전일 때만 유효하다
- 예약(Booking)은 밀접한 결합을 피하기 위해 다른 개념을 ID로 참조한다
핵심 개념
─────────────
Room (엔티티) Organizer (엔티티)
│ │
│ 참조됨 │ 참조됨
▼ ▼
┌───────────────────────────────────────────┐
│ Booking (엔티티) │
│-------------------------------------------│
│ 식별자: bookingId │
│ │
│ 필드: │
│ - roomId │ → Room 참조
│ - organizerId │ → Organizer 참조
│ - timeSlot (값 객체) │ → 유효해야 함
└───────────────────┬───────────────────────┘
│ 포함
▼
┌──────────────────────────────┐
│ TimeSlot (값 객체) │
│------------------------------│
│ 필드: │
│ - startTime │
│ - endTime │
│ 불변 조건: │
│ startTime < endTime │
└──────────────────────────────┘
도메인 모델에서 규칙이 명확하면, 구현 선택이 좋은 방향으로 제약받게 돼요.
다음 편에서는 도메인 주도 설계의 계층구조(Layered Architecture)가 무엇이고, 각 계층이 어떤 역할을 하는지 알아볼게요.
도메인 주도 설계 시리즈

