api를 만들기 위해서 총 3개의 클래스가 필요합니다.
- Request 데이터를 받을 Dto
- API요청을 받을 controller
- 트랜잭션, 도메인 기능 간의 순서를 보장하는 Service
- Web Layer
웹 레이어에는 컨트롤러와 JSP등의 뷰 템플릿 영역입니다.
이외에도 필터, 컨트롤러 어드바이스, 인터셉터 등 외부와의 요청과 응답에 관한 역할을 하는 영역입니다.
- Service Layer
- @Service에 사용되는 영역으로 controller와 dao의 중간 역할에 사용됩니다.
- @transection이 사용되는 영역이기도 합니다.
- Repository Layer
DataBase와 같이 데이터 저장소에 접근하는 영역입니다.
- Dtos
Dto는 계층간의 데이터 교환을 위한 객체이며 Dtos는 이 객체들의 영역입니다.
- Domain Model
- 모든 사람이 동일한 관점에서이해할 수 있고 공유할 수 있도록 단순화시킨 것을 도메인 모델이라고 합니다.
- @Entity가 사용된 영역을 도메인이라고 할 수 있습니다.
다만 VO처럼 값 객체들도 이 영역에 해당하므로 무조건 데이터베이스 테이블과 관계가 있어야하는 것은 아닙니다.
비지니스 처리를 담당해야하는 곳은 위 레이어중 도메인입니다.
Service 계층에서 비지니스 로직을 처리한다고 오해하고 있었지만 서비스는 트랜잭션, 도메인의 순서만을 보장합니다.
기존 사용하던 것처럼 서비스 계층에서 로직을 작성하는 예시를 들어보겠습니다.
@Transactional
public Order cancelOrder(int orderId){
// 데이터베이스로부터 주문 정보, 결제정보, 배송정보 조회
OrderDto order = ordersDao.selectOrders(orderId);
BillingDto billing - buillinDao.selectBilling(orderId);
DelivertDto delivery - deliveryDao.selelctDelivery(orderId);
//배송취소를 해야하는지 확인
String deliveryStatus = delivery.getStatus();
// 배송중이라면 배송취소로 변경
if ("IN_PROGRESS".equals(deliveryStatus)){
delivery.setStatus("CANCLE");
deliveryDao.update(delivery);
}
//각 테이블에 취소상태 update
order.setStatus("CANCLE");
ordersDao.update(order);
billing.setStatus("CANCLE");
deliveryDao.update(billing);
return order;
}
위 코드는 모든 비지니스 로직이 서비스 클래스 내부에서 처리됩니다.
그렇기 때문에 서비스 계층이 무의미하며, 객체가 단순히 데이터 덩어리로만 존재합니다.
이 코드를 도메인 모델에서 처리해보겠습니다.
@Transactional
public Order cancelOrder(int orderId){
// 데이터베이스로부터 주문 정보, 결제정보, 배송정보 조회
Orders order = ordersRepository.findById(orderId);
Billing billing = billingRepository.findByOrderId(orderId);
Delivery delivery = deliveryRepository.findByOrderId(orderId);
//배송취소를 해야하는지 확인
// 배송중이라면 배송취소로 변경
delivery.cancel();
//각 테이블에 취소상태 update
order.cancel();
billing.cancel();
return order;
}
주문, 결제, 배송은 각각 취소 처리만 담당하며, 서비스는 트랜잭션과 도메인간의 순서만 보장해주고 있습니다.