ilot
ilot의 블로그
ilot
전체 방문자
오늘
어제
  • 분류 전체보기 (17)
    • Algorithm (0)
    • Data Structure (0)
    • Database (0)
    • Operating System (0)
    • Network (0)
    • OOP (1)
    • Design Pattern (5)
    • Java (2)
    • Spring (5)
    • Mybatis (1)
    • JavaScript & TypeScript (0)
    • React (0)
    • Coding Test (2)
    • 독후감 (1)
    • 일상 (0)

블로그 메뉴

  • 홈
  • Github

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ilot

ilot의 블로그

[Spring] 서비스는 트랜잭션, 도메인의 순서 보장 역할만 제공한다
Spring

[Spring] 서비스는 트랜잭션, 도메인의 순서 보장 역할만 제공한다

2022. 11. 9. 14:00

서론

스프링에서는 @Controller, @Service, @Repository 등의 애노테이션을 사용하여 웹 계층을 분리하고 있다. 이 중 @Service는 사실상 @Component와 기능 차이가 없지만, 스프링에게 해당 클래스가 서비스 레이어 클래스라는 것을 알리는 역할을 한다고 한다. 그렇다면 Service Layer는 무슨 역할을 하는 걸까.

 

3 tier 아키텍처

3 tier 아키텍처

보통 스프링 프로젝트는 3 tier 방식으로 구성한다.

프레젠테이션 계층

  • 화면에 보여주는 기술을 사용하는 영역.
  • 컨트롤러에서 사용자의 요청에 맞는 응답처리를 진행하며, HTML엔진(thymeleaf), HTML등이 담당하는 영역.
  • Spring MVC 객체로, 컨트롤러, DispatcherServlet, 컨트롤러, 뷰, 모델이 포함된다.

서비스 계층

  • 순수한 비지니스 로직을 담고 있는 영역.
  • 이 영역의 설계는 고객의 요구사항과 정확히 일치해야 한다.
  • 프레젠테이션 계층과 데이터 엑세스 계층의 중간다리 역할을 한다.

데이터 엑세스 계층

  • 데이터를 어떤 방식으로 보관하고, 사용하는 가에 대한 설계가 들어가는 계층.
  • 일반적으로 DBMS를 많이 사용하지만, 상황에 따라서 API 호출, NoSQL, Kafka 등의 기술이 포함될 수 있다.
  • 데이터의 CRUD 연산을 수행하는 Mapper와 결과를 객체로 리턴하는 DAO을 포함한다.

 

오브젝트 중심 아키텍처

3 tier 아키텍처에 확장하여, Layer 간 데이터 전송 객체인 DTO와 특정 특정 도메인을 개념적으로 표현한 것인 Domain Model이 포함된 오브젝트 중심 아키텍처가 존재한다.

오브젝트 중심 아키텍처

Web Layer

  • 흔히 사용하는 Controller와 JSP 등의 뷰 템플릿 영역이다.
  • 이외에도 filter, interceptor, ControllerAdvice 등 외부 요청과 응답에 대한 전반적인 영역이다.
  • 3 tier 아키텍처의 프레젠테이션 계층과 유사하다.

Service Layer

  • @Service에 사용되는 서비스 영역이다.
  • 일반적으로 Controller와 DAO의 중간 영역으로 사용된다.
  • @Transactional이 사용되어야 하는 영역이다.
  • 3 tier 아키텍처의 서비스 계층과 유사하다.

Repository Layer

  • DB와 같이 데이터 저장소에 접근하는 영역이다.
  • DAO(Data Access Object)영역이다.
  • 3 tier 아키텍처의 데이터 엑세스 계층과 유사하다.

DTOs

  • DTO(Data Transfer Object)는 계층 간에 데이터 교환을 위한 객체다.
  • Web Layer에서 사용될 객체나 Repositroy Layer에서 결과로 넘겨주는 객체 등이다.

Domain Model

  • 도메인이라 불리는 개발 대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화시킨 것을 도메인 모델이라고 한다. (ex. 택시앱에서 배차, 탑승, 요금 등은 모두 도메인)
  • JPA의 경우 @Entity를 사용된 영역이 도메인 모델이다.
  • 다만, 무조건 DB의 테이블과 관계가 있어야만 도메인은 아니다.
  • VO(Value Object)처럼 값 객체들도 이영역 해당된다.

 

서비스 차원에서 - 3 tier 아키텍처 vs 오브젝트 중심 아키텍처

주문 취소에 대한 메서드가 있을 때, 각 아키텍처 방식으로 서비스 단에서 cancelOrder를 구현해보았다.

예시 - 3 tier 아키텍처

@Transactional
public Order cancelOrder(int orderId) {
  // 1) 주문정보, 결제정보, 배송정보 조회
  OrdersDto order = ordersDao.selectOrders(orderId);
  BillingDto billing = billingDao.selectBilling(orderId);
  DeliveryDto delivery = deliveryDao.selectDelivery(orderId);
  
  // 2) 배송 취소 여부 확인
  String deliveryStatus = delivery.getStatus();
  
  // 3) 배송중이라면 배송 취소
  if ("IN_PROGRESS".equals(deliveryStatus)) {
    delivery.setStatus("CANCEL");
    deliveryDao.update(delivery);
  }
  
  // 4) 각 테이블에 취소상태 갱신
  order.setStatus("CANCEL");
  ordersDao.update(order);
  
  billing.setStatus("CANCEL");
  billingDao.update(billing);
  
  return order;

}
  • Service에서 모든 비지니스 로직을 처리하기 때문에 구현이 매우 쉽고 단순하지만 구조가 복잡해질 수록 모듈화의 복잡도도 높아지게 된다.
  • order, billing, delivery는 단순히 정보만 담겨있고, 모든 로직은 Service 단에 존재한다.

빈약한 도메인 오브젝트

  • 단순히 정보만 담겨있는 오브젝트를 빈약한 (Anemic) 오브젝트라 함
  • 도메인 오브젝트 기능이라 하면 도메인 오브젝트의 비즈니스 로직이라 볼 수 있음
  • 빈약한 도메인 오브젝트의 경우 비즈니스 로직이 전부 서비스 계층에 있기 때문에 거대 서비스 계층구조와 비슷함
  • 도메인 오브젝트는 독립적으로 존재하면서 일관된 구조의 정보를 담아서 전달하는데만 사용됨
  • SQL에 의존적인 데이터 방식보다 유연하고 간결하지만, 서비스 계층의 메소드에 대부분의 비즈니스 로직이 있기 때문에 재사용성이 떨어지고 중복의 문제가 발생하기 쉬움

예시 - 오브젝트 중심 아키텍처

@Transactional
public Order cancelOrder(int orderId) {
  // 1) 주문정보, 결제정보, 배송정보 조회
  OrdersDto order = ordersDao.selectOrders(orderId);
  BillingDto billing = billingDao.selectBilling(orderId);
  DeliveryDto delivery = deliveryDao.selectDelivery(orderId);

  // 2)배송 취소 여부 확인 - 3)배송중이라면 배송취소
  delivery.cancel();

  // 4)각 테이블에 취소상태 갱신
  order.cancel();
  biling.cancel();

  return order;
}
  • 객체에 객체가 수행해야 하는 업무를 분담시키는 것으로써 Service에서는 트랜잭션, 도메인 간의 순서보장의 역할만을 제공하고 비지니스 로직을 Domain에서 처리하는 방식이다.
  • order, billing, delivery 각각에 cancel 기능이 담겨있어, 다른 Service에서도 재사용하기 쉬워지고, 코드 가독성이 높아졌다.

풍성한 도메인 오브젝트

  • 정보 저장 뿐만이 아니라, 내부의 정보를 이용하는 기능도 가지고 있는 오브젝트를 풍성한 오브젝트라 한다.
  • 데이터와 데이터를 사용하는 로직을 모아두기 때문에 응집도가 높음
  • 어떤 비즈니스 로직은 특정 도메인 오브젝트와 깊은 관계가 있을 수 있음
  • 해당 로직을 도메인 오브젝트에 넣고, 서비스 계층의 비스니스 로직에서 재사용하도록 함

 

결론

  • Service는 비즈니스 로직을 담는 것이 아닌, 트랜잭션 처리와 도메인 모델간의 순서 보장의 역할을 부여하는 것을 지향해야 한다. 비즈니스 로직은 도메인 모델에 넣자.
  • 이로써 얻는 이점은, 재사용성을 높이고 코드 가독성이 좋아진다.

 

 

출처
https://ksb-dev.tistory.com/m/210
https://incheol-jung.gitbook.io/docs/study/ddd-start/1
https://hongs-coding.tistory.com/119
토비의 스프링 3.1 Vol. 1 스프링의 이해와 원리 : http://www.yes24.com/Product/Goods/7516721
스프링 부트와 AWS로 혼자 구현하는 웹 서비스 : http://www.yes24.com/Product/Goods/83849117

 

'Spring' 카테고리의 다른 글

[Spring] Async  (0) 2022.10.28
[Spring] 트랜잭션  (0) 2022.10.19
[Spring] 왜 Spring 인가  (0) 2022.08.14
[Spring Batch] Tasklet & Chunk 예시  (0) 2022.07.13
    'Spring' 카테고리의 다른 글
    • [Spring] Async
    • [Spring] 트랜잭션
    • [Spring] 왜 Spring 인가
    • [Spring Batch] Tasklet & Chunk 예시
    ilot
    ilot
    _

    티스토리툴바