본문 바로가기

Database & ORM/JPA 프로젝트

8. 도메인, 객체 지향, 비즈니스 로직

어디서 비즈니스 로직을 처리해야 할까?

서비스가 아니라 도메인에서 비즈니스 로직을 처리해야 한다.

JPA로 Domain을 사용하기 이전에, 비즈니스를 처리하는 곳은 Service 계층이었다.
이러한 방식을 트랜잭션 스크립트라고 한다.

트랜잭션 스크립트

모든 로직이 Service 클래스 내부에서 처리 된다. 그러다 보니 서비스 계층이 무의미하며, DAO로 값을 전달하는 VO 객체는 단순히 데이터 덩어리 역할만 하게 된다.
객체 지향적 개발이라기 보다는 절차지향적인 개발에 가깝게 볼 수 있다.

@Transactional
public Order cancelOrder(int orderId) {

	//1) 데이터베이스로부터 주문정보 (Orders), 결제정보 (Billing), 배송정보 (Delivery) 조회
    OrdersDto order = ordersDao.selectOrders(orderId);
    BillingDto billing = billingDao.selectBilling(orderId);
    DeliberyDto delivery = deliveryDao.selectDelivery(orderId);
    
	//2) 배송 취소를 해야 하는지 확인
    String deliveryStatus = delivery.getStatus();
    
	//3) 배송 중이라면 배송취소로 변경
    if("IN_PROGRESS".equals(deliberyStatus)){
    	delivery.setStatus("CANCEL");
        delivery.update(delivery);
     }

	//4) 각 테이블 상태 취소 상태 Update
     order.setStatus("CANCEL");
     orderDao.update(order);
     
     billing.setStatus("CANCEL");
     deliveryDao.update(billing);
     
     return order;
     
}

도메인 모델

핵심 비즈니스 로직은 도메인이 담당한다.
서비스 메소드는 트랜잭션과 도메인 간의 순서만 보장해준다.

아래 예시를 보면 order, billing, delivery 도메인이 각자 본인의 취소 이벤트 처리를 한다. 서비스에서는 @Transactional로 트랜잭션과, 각 도메인 별 cancel() 호출 순서만 담당하고 있다.

@Transactional
public Order cancelOrder(int orderId){

	//1) 데이터베이스로부터 주문정보 (Orders), 결제정보 (Billing), 배송정보 (Delivery) 조회
	OrdersDto order = ordersRepository.findById(orderId);
	BillingDto billing = billingRepository.findByOrderId(orderId);
	DeliveryDto delivery = deliveryRepository.findByOrderId(orderId);
    
	//2) Delivery 내부에서 배송 취소를 해야 하는지 확인
    //3) 배송 중이라면 배송취소로 변경
	delivery.cancel();
    
	//4) order, billing 순으로 취소
	order.cancel();
	billing.cancel();

	return order;
}

도메인 모델 적용하여 주문 취소 기능 구현

Service

OderService는 id로 order을 찾아서 Order 도메인에 구현된 cancelOrder()을 실행한다.

Domain

Order의 cancelOrder에서 비니지스 핵심 로직이 구현되어 있다.
Delivery 취소와 OrderItem 취소도 각 도메인에 로직을 구현한다.

주문 상품(OrderItem) 취소 시 , 상품(Item)의 재고량은 증가한다.
이렇게 객체지향 프로그래밍은, 절차지향 프로그래밍과 달리, 객체간의 호출과 처리를 위임하는 대화를 한다. ex) item.addStock(count)