Web/📗 Spring

Service에서 비지니스 로직을 처리한다? [Spring / 스프링 부트와 AWS로 혼자 구현하는 웹 서비스]

키깡 2022. 7. 18.
728x90

API를 만들기 위해 총 3개의 클래스 필요

  • Request 데이터를 받을 Dto
  • API 요청을 받을 Controller
  • 트랜잭션, 도메인 기능 간 순서를 보장하는 Service

Service에서 비지니스 로직을 처리한다?

(X)

Image

  • Web Layer

    • 컨트롤러(@Controller)와 JSP/Freemarker 등 뷰 템플릿 영역
    • 필터(@Filter), 인터셉터, 컨트롤러 어드바이스 등 외부 요청과 응답에 대한 전반적 영역
  • Service Layer

    • @Service에 사용되는 서비스 영역
    • 일반적으로 Controller와 Dao의 중간 영역에서 사용됨.
    • @Transactional이 사용되어야 하는 영역
  • Repository Layer

    • Database와 같이 데이터 저장소에 접근하는 영역 (Dao 영역과 유사)
  • Dtos

    • Dto는 계층 간에 데이터 교환을 위한 객체. Dtos는 이들의 영역.
    • 뷰 템플릿 엔진에서 사용될 객체나 Repository Layer에서 결과로 넘겨준 객체 등
  • Domain Model

    • 도메인(택시앱일 때 배차, 탑승, 요금 등)이라 불리는 개발대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화 시킨 것
    • @Entity역시 도메인 모델
    • 테이블과 관계가 있는 것들 뿐 아니라 VO처럼 각 객체들도 해당
  • 이 중 비지니스 처리를 담당하는 곳은 Domain

Domain에서 비지니스 처리하기

  • 다음과 같은 주문 취소 로직이 있다고 하자.
@Transactional
public Order cancelOrder(int orderId){
        1) 데이터베이스로부터 주문정보 ( Orders ), 결제 정보 (Billing), 배송정보 (Delivery) 조회

        2) 배송취소를 해야 하는지 확인

        3) (if 배송중이라면){
            배송 취소 변경
        }

        1) 각 테이블에 취소 상태 Update
}
  • 기존에 서비스로 처리하던 방식 (트랜잭션 스크립트)

: 모든 로직이 서비스 클래스 내부에서 처리 됨. (상태 set하는 것)

그러다 보니 서비스가 무의미하고, 객체란 단순히 데이터 덩어리 역할만함.

@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);

        billing.setStatus("CANCEL");
        deliveryDao.update(billing);
        return order;
}
  • 도메인 모델
    order, billing, delivery가 각자 본인의 취소 이벤트 처리를 하며, 서비스 메소드는 트랜잭션과 도메인 간의 순서만 보장해 줌.
@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();

        return order;
}

댓글