네이밍 규칙 ( 기본 ) 저번에 배웠던 내용에서 추가적으로 정리해보겠습니다.
모든 식별자는 역할과 기능을 직관적 으로 표현하는 것이 중요합니다.
오늘도 어김없이 대형마트로 예를 들어보겠습니다.
마트의 부서 (조직)
고객 서비스 센터 = com.mart.customer
재고 관리 부서 = com.mart.inventory
결제 시스템 = com.mart.payment
이벤트&할인 = com.mart.promotion
부서에서 일하는 담당자
고객 서비스 센터 / CustomerService 고객 문의 처리
재고 관리 부서 / InventoryManager 상품 재고 관리
결제 시스템 / PaymentProcessor 결제 처리
이벤트 & 할인 / DiscountCalculator 할인율 계산
직원의 '직무' <- ★★★★★
고객이 물건을 구매 / processPurchase() 고객의 구매를 처리
장바구니에 추가 / addToCart() 상품을 장바구니에 추가
가격 계산 / calculatePrice() 결제 시 총 가격을 계산
결제 처리 / processPayment() 고객의 결제를 처리
쿠폰 적용 / applyCoupon() 할인 쿠폰을 적용추가적으로 [동사 + 명사] 를 조합하여 동작을 명확히 표현하는 것이 중요합니다.
계산 담당자라면? 일하기() 보다는 계산하기() 가 명확한 것 처럼 메서드를 지어야 합니다. 이 메서드가 무슨 일을 하는 지 바로 알 수 있어야 합니다.
com/mart
├── customer/ (고객 서비스)
│ ├── CustomerService.java
│ └── Customer.java
├── inventory/ (재고 관리)
│ ├── InventoryManager.java
│ └── Product.java
├── payment/ (결제 시스템)
│ ├── PaymentProcessor.java
│ ├── CreditCardPayment.java
│ ├── CashPayment.java
├── logistics/ (배송 관리)
│ ├── DeliveryTracker.java
│ ├── Shipment.java
├── promotion/ (이벤트 & 할인)
│ ├── DiscountCalculator.java
│ ├── Coupon.java
이런식으로 작성하게 되면
" 아 customer 패키지 에서는 고객 관련된 일을 처리하는 구나 " 라는 걸 바로 알 수 있습니다.
장점 :
유지보수와 테스트가 편리함
➡ 마트의 재고 관리 시스템을 예로 들어 보세요.
DDD에서는 각 기능(주문, 결제, 재고 등)을 독립적인 도메인 객체로 나눕니다.
예를 들어, 재고 도메인은 재고 관리, 입고, 출고와 같은 기능을 담당하는 클래스를 따로 두죠.
이렇게 나누면 각 도메인만 수정하면 되므로 유지보수가 쉽습니다.
또, 각 도메인 객체에 대한 테스트도 따로 할 수 있기 때문에 버그를 빠르게 찾고 수정할 수 있습니다.
객체지향적인 설계를 가능하게 함
➡ 마트의 상품 관리 시스템을 예로 들어 보세요.
DDD에서는 비즈니스 객체들을 실제 세계와 유사한 객체들로 모델링합니다.
예를 들어, 상품, 주문, 고객이 각각 독립적인 객체로 설계되죠.
이 객체들은 자기 자신만의 속성(예: 상품은 이름, 가격 속성)과 메서드(예: 주문은 주문 처리 메서드)가 있어요.
이렇게 객체지향적인 설계를 사용하면, 프
로그램이 실제 세계의 비즈니스 흐름을 그대로 반영하게 되어 이해하기 쉽고 확장성도 뛰어납니다.
비즈니스 로직과 소프트웨어 모델링 간의 연결이 강함
➡ 마트의 고객 관리 시스템을 예로 들어 보세요.
DDD는 비즈니스 로직(상품을 팔고, 주문을 처리하는 것)과 소프트웨어 모델(객체, 클래스 등)을 강하게 연결시킵니다.
예를 들어, 고객 객체는 고객의 정보뿐만 아니라 고객이 주문할 때 필요한 비즈니스 로직도 함께 포함합니다.
이렇게 하면 소프트웨어가 비즈니스의 규칙을 자연스럽게 따르게 되어, 실제 비즈니스 프로세스를 코드에서 그대로 반영할 수 있습니다.
결과적으로, 비즈니스 측 요구사항을 시스템에 쉽게 반영하고, 변경 사항이 생기더라도 빠르게 수정할 수 있어요.
단점 :
도메인의 복잡성이 그대로 반영됨
➡ 마트의 창고 관리 시스템을 만든다고 가정해 보세요.
창고에는 상품이 있고, 상품마다 유통기한, 공급업체, 입출고 기록 등 다양한 정보가 있음.
이 모든 것을 객체로 설계하면 코드가 너무 복잡해짐!
과도한 도메인 주도 설계는 유연성을 떨어뜨림
➡ "마트의 주문 시스템"을 만든다고 가정해 보세요.
주문, 결제, 배송 등을 객체로 만들어 각각의 규칙을 적용하면 코드가 탄탄해짐.
하지만 새로운 결제 방식(예: 페이팔 결제)을 추가하려면 도메인 모델도 함께 수정해야 해서 개발이 번거로움.
즉, 너무 엄격하게 설계하면, 새로운 기능을 추가하기 어려워질 수 있음!
초기 설계에 시간이 많이 걸림
➡ 마트 POS 시스템(계산대 프로그램)을 만든다고 가정해 보세요.
상품, 할인, 결제, 쿠폰, 멤버십 등 다양한 개념을 정리해야 함.
처음부터 도메인을 정교하게 설계하려면 분석과 논의가 오래 걸림.
반면, 간단하게 서비스/컨트롤러를 만들어 개발하면 빠르게 구현 가능!
도메인 설계는 소프트웨어의 하위 기초 요소를 결정하는 중요한 작업
➡ 마트의 재고 관리 시스템을 설계한다고 가정해 보세요.
"상품"이라는 개념을 먼저 정의해야 하고,
상품을 관리하는 "창고", "재고 수량", "공급업체" 같은 개념이 뒤따라옴.
기본 개념을 잘못 정하면, 나중에 전체 시스템을 다시 설계해야 할 수도 있음!
com/mart
├── manager/
│ ├── CustomerManager.java (고객 관리)
│ ├── InventoryManager.java (재고 관리)
│ ├── PaymentManager.java (결제 관리)
│ ├── DeliveryManager.java (배송 관리)
├── service/
│ ├── CustomerService.java (고객 서비스)
│ ├── InventoryService.java (재고 서비스)
│ ├── PaymentService.java (결제 서비스)
│ ├── DeliveryService.java (배송 서비스)
이런식으로 작성하게 되면
" 계산을 처리하는 건 service 패키지로 가면 되겠구나 "라는 걸 바로 알 수 있습니다.
장점 :
구조를 쉽게 파악할 수 있다
➡ 마트의 POS 시스템을 개발한다고 생각해 보세요.
만약 프로젝트 구조가 계층형 구조라면, 각 계층별로 역할이 명확해져서 어디서 어떤 작업을 하는지 쉽게 알 수 있음.
예를 들어, Controller 패키지는 사용자의 요청을 받는 역할을, Service 패키지는 비즈니스 로직을 처리하는 역할을 함.
그래서 패키지 구조만 보고도 시스템의 흐름을 쉽게 파악할 수 있음.
각 계층별로 집중할 수 있다
➡ 마트의 결제 시스템을 살펴보세요.
만약 결제 기능을 보고 싶다면 Service 패키지에 있는 결제 관련 코드만 보면 됨.
Controller 패키지를 보면 사용자가 요청한 부분(예: 결제 화면)이 어떤 식으로 동작하는지 알 수 있고,
비즈니스 로직만 보고 싶다면 Service 패키지를 살펴보면 됨.
각각의 패키지가 책임을 분리하고 있어, 필요한 부분만 빠르게 찾을 수 있음.
단점 :
도메인별 응집도가 낮다
➡ 마트의 재고 관리 시스템을 생각해 보세요.
계층형 구조에서는 하나의 패키지 안에 여러 도메인(예: 상품, 재고, 주문)이 섞여 있을 수 있음.
이러면 도메인별로 코드가 분리되지 않아 어떤 클래스가 어떤 도메인과 관련이 있는지 파악하기 힘들어질 수 있음.
예를 들어, 상품과 주문 도메인의 비즈니스 로직이 Service 패키지 안에 섞여 있으면 나중에 변경이나 확장할 때 혼란이 생김.
유스케이스 표현이 어렵다
➡ 마트에서 고객이 상품을 주문하는 흐름을 생각해 보세요.
계층형 구조에서는 각 계층이 나누어져 있기 때문에 사용자의 행위(유스케이스)와 관련된 모든 흐름을 표현하기 어려움.
Controller, Service, Repository로 나누다 보니 고객이 상품을 주문하는 과정(유스케이스)을 직관적으로 파악하기 힘들어질 수 있음.
쉽게 설명하면 프로젝트의 규모에 따라서 구조를 선택하는 것이 바람직!
1. 작은 프로젝트라면 계층형 구조를 따라가는 것이 수월할 수 있음!
2. 그 외 대규모 프로젝트라면 도메인 구조를 따라가는 것이 옳음!
3. 단일 책임 원칙 (Single Responsibility Principle, SRP) ★★★★★ 잘 지켜야함.
한 클레스는 오직 하나의 책임만 가져야 한다