API를 구현하려면 총 3개의 클래스가 필요하다.
보통 Service는 비즈니스 로직을 처리한다고 오해하는데, 사실 트랜잭션, 도메인 간의 순서를 보장하는 역할만 한다.
그럼 비즈니스 로직은 누가 처리할까?
Spring 웹 계층
Web(Controller) Layer
Service Layer
"잘 와닿지 않는다. 좀 더 자세하게 알아보자"
Repository Layer
DTO
Domain Model
5개의 레이어 중에서 비즈니스 처리를 담아하는 곳은 Domain이다.
트랜잭션 스크립트
public class Example {
@Transactional
public Order cancelOrder(int orderId) {
// 1. 데이터베이스로부터 Orders, Billing, Delivery 조회
OrdersDto order= ordersDao.selectOrders(orderId);
BillingDto billing = billingDao.selectBilling(orderId);
DeliveryDto delivery = deliveryDao.selectDelivery(orderId);
// 2. 배송 취소를 해야하는지 확인
String deliveryStatus = delivery.getStatus();
// 3. if(배송 중이라면) 배송 취소로 변경
if("IN_PROGRESS".equals(deliveryStatus)) {
delivery.setStatus("CANCEL");
deliveryDao.update(delivery);
}
// 4. 각 테이블에 취소 상태 update
order.setStatus("CANCEL");
ordersDao.update(order);
biling.setStatus("CANCEL");
deliveryDao.update(biling);
return order;
}
}
서비스에서 처리하는 방식을 트랜잭션 스크립트라고 한다. 모든 로직이 서비스 클래스 내부에서 처리되다보니 서비스 계층이 무의미하고, 객체가 단순히 데이터 덩어리 역할만 하게 된다.
도메인 모델
public class Example {
@Transactional
public Order cancelOrder(int orderId) {
// 1. 데이터베이스로부터 Orders, Billing, Delivery 조회
Orders order = ordersRepository.findById(orderId);
Billing billing = billingRepository.findByOrderId(orderId);
Delivery delivery = deliveryRepository.findByOrderId(orderId);
// 2. 배송 취소를 해야하는지 확인
// 3. if(배송 중이라면) 배송 취소로 변경
delivery.cancel();
// 4. 각 테이블에 취소 상태 update
order.cancel();
billing.cancel();
}
}
order, billing, delivery가 각자 본인의 취소 이벤트를 처리한다. 서비스 메서드는 트랜잭션과 도메인 간의 순서만 보장한다.
이 프로젝트에서는 도메인 모델을 다룰 것이다.