- 어플리케이션의 핵심 비즈니스 로직을 반영하는 영역 - domain problem을 모델링한 객체로 이루어짐 - 주로 상태(state)와 행위(behavior)를 캡슐화 - 데이터 일관성을 위한 유효성검사(Validation) 포함 - Entity와 Value Object로 나뉘는 경우가 많다.
서비스
- 도메인 객체간의 협력을 조정, 도메인에 적합하지 않은 복합적 비즈니스 로직을 처리하는 계층 - 상태를 가지지 않음 - 트랜잭션 관리, 외부 시스템 호출, 도메인 간 상호작용을 책임짐 - 도메인의 비즈니스 규칙을 유지하면서 이를 효과적으로 활용하도록 돕는 조정자 역할
차이
두 개념은 역할과 책임의 관점에서 다름
개념명
특징
도메인
- 비즈니스의 핵심 규칙을 표현 - 주로 데이터를 보유하고, 해당 데이터와 관련된 동작(행위)을 정의 - 비즈니스 로직 중, 도메인 자체가 책임져야 하는 로직을 포함 - ex. User - "사용자가 18세 이상이어야 회원가입 가능" 로직
서비스
- 도메인 객체 간의 협력을 조정하거나, 복합적 비즈니스 로직을 처리 - 도메인이 책임지기 애매한 비즈니스 로직(도메인 간 교차적 혹은 외부 시스템과 관련된 로직) - 상태를 가지지 않고, 순수하게 로직만 포함하는 경우가 많음
서비스가 도메인인 이유
1. 서비스 또한 도메인 계층의 일부로 간주될 수 있기 때문 2. 도메인 모델(Domain Model) 패턴에서 서비스는 도메인 로직을 조정하고 결합하기 위해 설계된 도메인 서비스로 불림. 3. 하지만 정밀한 범위에서 서비스는 도메인 모델 그 자체라기 보다, 도메인 객체를 활용하는 조정자 역할
개념명
정의
예
도메인 로직
- 도메인 객체 내부에 정의된 로직 - 단일 엔티티에 국한된 비즈니스 규칙
public class User { private int age; public boolean isEligible() { return age >= 18; } }
-------------
public class Product { private String name; private int stock;
public void decreaseStock(int quantity) { if (quantity > stock) { throw new IllegalArgumentException("재고가 부족합니다."); } stock -= quantity; } }
서비스 로직
- 여러 도메인 객체를 조합하거나, - 외부 시스템과의 연계를 포함한 로직 - 상태를 가지지 않고, 특정 행위만 담당
@Service public class UserService { public void registerUser(User user) { if (user.isEligible()) { // Repository를 이용해 저장 userRepository.save(user); } else { throw new IllegalArgumentException( "사용자는 등록 자격이 없습니다."); } } }
-------------------
@Service public class OrderService { private final ProductRepository productRepository; private final OrderRepository orderRepository;
public void placeOrder(Long productId, int quantity) { Product product = productRepository.findById(productId) .orElseThrow(() -> new IllegalArgumentException("상품을 찾을 수 없습니다."));
product.decreaseStock(quantity); // 도메인 로직 호출 productRepository.save(product);
Order order = new Order(product, quantity); orderRepository.save(order); } }
비고
1. DTO는 도메인과 완전히 다른 목적을 가진 객체임. Data Transfer Object, 말 그대로 데이터 전달에 사용. 주로 계층 간(Controller-Service-Client) 데이터 교환에 쓰이며, 상태와 행위를 포함하지 않고 순수하게 데이터를 담기만 함. 예) public class ProductResponseDto { private String name; private int stock; // 이하 생성자와 getter만 포함 }