Post

도메인(Domain)이 뭐냐고?

CS 개념이 아닌, 우리가 프로젝트 회의에서 사용하는 비즈니스 도메인의 뜻을 이야기하는 것이 목적이다.

도메인(Domain)이 뭐냐고?

도메인(Domain)이 뭐냐고?

도메인 Domain

도메인이란 소프트웨어가 해결하려는 주제나 문제 영역을 뜻한다.
즉, “이 프로그램이 다루는 게 무엇인가?”를 생각하면 된다.

도메인의 예시

우리가 사용하는 다양한 소프트웨어는 각자 해결하려는 문제가 다르다.

소프트웨어해결하려는 문제(도메인)예시
은행 앱금융 서비스계좌 관리, 송금, 대출
쇼핑몰 사이트온라인 쇼핑상품 검색, 주문, 결제
택시 호출 앱이동 서비스택시 호출, 요금 계산
게임엔터테인먼트캐릭터 성장, 아이템 획득

이처럼 도메인은 소프트웨어가 다루는 주제이며, 도메인을 이해해야 좋은 프로그램을 만들 수 있다.


도메인은 단순한 데이터가 아니다!

도메인은 데이터(정보)만 있는 것이 아니라, 규칙과 행동(로직) 도 포함한다.

예시 1: 쇼핑몰 도메인
쇼핑몰에서는 상품을 팔고, 주문을 받고, 결제를 처리한다.
하지만 단순히 상품 정보만 저장하는 것이 아니라, 여러 규칙이 있다.

  • 상품 가격은 0원보다 커야 한다. (도메인 규칙)
  • VIP 고객은 10% 할인을 받는다. (비즈니스 로직)
  • 한 번 결제한 주문은 취소할 수 없다. (비즈니스 규칙)

이처럼 도메인은 데이터 + 규칙 + 로직을 포함하는 개념이다.


도메인을 코드로 표현하기

소프트웨어에서 도메인을 코드로 만들 때는, 몇 가지 중요한 개념이 있다.

개념설명예시 (쇼핑몰 도메인)
엔터티(Entity)고유한 ID가 있는 객체상품, 주문, 고객
값 객체(Value Object)ID 없이 값 자체가 중요한 객체가격, 주소
도메인 서비스(Domain Service)비즈니스 로직을 담당하는 서비스할인 계산, 결제 처리
이벤트(Domain Event)특정한 일이 발생했을 때 알리는 개념“주문 완료됨”

예제 코드 (간단한 주문 시스템)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Product:
    def __init__(self, name, price):
        if price <= 0:
            raise ValueError("상품 가격은 0원보다 커야 합니다.")  # 도메인 규칙
        self.name = name
        self.price = price

class Order:
    def __init__(self, product, quantity):
        self.product = product
        self.quantity = quantity
        self.total_price = product.price * quantity

# 상품 생성
apple = Product("사과", 1000)

# 주문 생성
order = Order(apple, 3)
print(order.total_price)  # 3000 출력

위 코드에서 상품(Product)과 주문(Order)은 도메인의 핵심 개념이다.
또한, “상품 가격은 0원보다 커야 한다” 라는 도메인 규칙을 코드로 표현했다.


그러므로 도메인을 잘 설계하면 ?

  1. 비즈니스 규칙이 명확해진다.
    → “할인 적용은 어디서 하지?” 같은 혼란이 줄어든다.

  2. 변경이 쉬워진다.
    → 예를 들어 “VIP 고객은 20% 할인”으로 변경해도 쉽게 수정할 수 있다.

  3. 다른 개발자와 협업이 쉬워진다.
    → “이 시스템이 하는 일이 뭔지” 쉽게 설명할 수 있다.


도메인을 먼저 이해하고 개발하면, 더 좋은 프로그램을 만들 수 있다! 🚀


조금 깊게 들어가보자

도메인의 구성 요소

도메인은 단순히 주제가 아니라, 소프트웨어에서 모델링할 필요가 있는 개념들의 집합이다. 이를 DDD에서 다루는 주요 개념을 통해 살펴보면 다음과 같다.

개념설명예시 (전자상거래 도메인)
엔터티(Entity)고유한 식별자를 가지는 객체사용자, 주문, 상품
값 객체(Value Object)불변하며, 고유한 식별자가 없는 객체주소(Address), 가격(Price)
애그리게이트(Aggregate)관련된 엔터티와 값 객체를 하나로 묶은 단위주문(Order) → 주문 항목(OrderItem) 포함
도메인 서비스(Domain Service)엔터티나 값 객체에 속하지 않는 비즈니스 로직결제 처리, 할인 계산
이벤트(Domain Event)도메인에서 발생하는 중요한 사건주문 생성됨, 결제 완료됨
리포지토리(Repository)엔터티를 저장하고 검색하는 인터페이스주문 저장소, 상품 저장소

도메인은 단순히 데이터 모델이 아니라, 비즈니스 로직과 규칙을 포함하는 핵심 계층이다.

  • 데이터 저장을 담당하는 것이 아니라, 데이터를 처리하는 규칙을 정의하는 것
    • “상품 가격은 0원 이하일 수 없다” → 도메인 규칙
    • “VIP 고객은 10% 할인을 받는다” → 도메인 로직
    • “주문 후 30분이 지나면 취소할 수 없다” → 도메인 정책

이러한 규칙들은 애플리케이션의 핵심 로직이므로, 도메인 계층에서 잘 관리해야 한다.


도메인과 소프트웨어 개발

소프트웨어 설계에서 도메인을 효과적으로 다루는 방법 중 하나가 도메인 주도 설계(DDD, Domain-Driven Design) 이다.
DDD에서는 도메인을 중심으로 시스템을 설계하며, 도메인 모델을 통해 현실 세계의 개념을 코드로 반영한다.

  • 도메인 모델을 중심으로 설계한다.
    • 도메인의 개념을 엔터티, 값 객체, 애그리게이트 등으로 표현
    • 도메인 서비스와 이벤트를 활용해 로직을 구성
    • 유비쿼터스 언어를 사용하여 비즈니스 전문가와 개발자가 동일한 개념을 공유
  • 도메인 모델을 검증하기 위해 테스트 주도 개발(TDD)을 활용한다.
    • 도메인 로직이 올바르게 동작하는지 테스트 코드로 검증
    • 변경이 용이한 구조를 만들기 위해 리팩토링 반복

보통의 회사에서 도메인을 다루는 과정

회사에서 소프트웨어를 개발할 때, 도메인은 단순한 개념이 아니라 프로젝트의 중심이 된다. 일반적인 기업에서는 다음과 같은 단계로 도메인을 다룬다.

도메인 이해 단계(비즈니스 분석) -> 도메인 모델링 단계(도메인 모델 설계) -> 구현 단계(TDD + 개발) -> 실제 서비스 운영(배포 & 유지보수)


1. 도메인 이해 단계 (비즈니스 분석)

도메인을 정의하는 과정

  • 프로젝트가 해결하려는 비즈니스 문제를 정의한다.
  • 도메인 전문가(기획자, 사업부, 고객)와 협업하여 도메인을 분석한다.
  • 유비쿼터스 언어(Ubiquitous Language)를 정리하여 팀원들이 같은 용어를 사용하게 한다.

쇼핑몰 개발을 한다면?

문제 정의:
“사용자가 온라인에서 상품을 주문하고 결제할 수 있는 쇼핑몰을 만든다.”

핵심 개념 도출:

  • 상품 (Product)
  • 주문 (Order)
  • 결제 (Payment)
  • 배송 (Delivery)

유비쿼터스 언어 정리:

  • 주문(Order): 고객이 상품을 구매하는 행위
  • 결제(Payment): 고객이 상품 대금을 지불하는 과정
  • 배송(Delivery): 고객이 주문한 상품을 받는 과정

즉, 팀원들이 모두 같은 용어를 사용하도록 정리하여 혼선을 방지하고 개발을 수월하게 진행할 수 있도록 해야한다.


2. 도메인 모델링 단계

도메인 모델 설계

  • 도메인에서 중요한 개념을 코드로 정의한다.
  • 엔터티(Entity), 값 객체(Value Object), 애그리게이트(Aggregate) 등을 식별한다.
  • 데이터 흐름과 관계를 고려한 설계를 진행한다.

쇼핑몰 예시

개념설명
상품(Product)상품명, 가격 등의 정보를 갖는다.
주문(Order)여러 개의 상품을 포함하고, 결제 상태를 관리한다.
결제(Payment)주문과 연결되며, 결제 방법(카드, 계좌이체 등)을 포함한다.
배송(Delivery)주문이 완료된 후 고객에게 상품을 전달하는 과정이다.

예제 코드 (도메인 모델)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Product:
    def __init__(self, name, price):
        if price <= 0:
            raise ValueError("가격은 0원보다 커야 합니다.")
        self.name = name
        self.price = price

class Order:
    def __init__(self, products):
        if not products:
            raise ValueError("한 개 이상의 상품이 필요합니다.")
        self.products = products
        self.total_price = sum(product.price for product in products)

class Payment:
    def __init__(self, order, method):
        self.order = order
        self.method = method
        self.status = "Pending"

    def complete_payment(self):
        self.status = "Completed"

3. 구현 단계 (TDD + 개발)

테스트 주도 개발 (TDD)과 도메인 검증

  • 도메인 모델이 올바르게 동작하는지 테스트 코드 작성 후 개발
  • 예외 상황 (상품이 없는 주문, 결제 실패 등)도 고려하여 검증

쇼핑몰 테스트 코드 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
import unittest

class TestOrder(unittest.TestCase):
    def test_create_order(self):
        product1 = Product("노트북", 1500000)
        product2 = Product("마우스", 50000)
        order = Order([product1, product2])

        self.assertEqual(order.total_price, 1550000)  # 총 가격이 맞는지 확인

    def test_empty_order(self):
        with self.assertRaises(ValueError):
            Order([])  # 상품 없이 주문하면 오류 발생

4. 실제 서비스 운영 (배포 & 유지보수)

서비스 배포 및 지속적인 개선

  • 도메인 모델을 기반으로 실제 데이터베이스와 연결하고, API를 개발한다.
  • 운영하면서 새로운 비즈니스 요구사항이 추가되면 도메인 모델을 점진적으로 개선한다.
  • A/B 테스트데이터 분석을 통해 도메인을 최적화한다.

실제 운영 예시 (쇼핑몰)

  1. 초기에 신용카드 결제만 지원했지만, 고객 요청으로 카카오페이, 애플페이 추가
    Payment 도메인 모델을 수정하여 결제 방법을 확장

  2. 배송 지연 문제 해결을 위해 배송 추적 기능 추가
    Delivery 모델에 배송 상태(배송 준비, 배송 중, 배송 완료) 필드 추가


참고

This post is licensed under CC BY 4.0 by the author.