Skills/Spring

Spring - Spring Web Layer

aoaa 2022. 7. 27. 15:01

 Spring Boot로 아키텍쳐 설계 시 이해를 돕고자 Spring에서 Web 기반 프로그램을 만들 때 어떤 계층이 존재하고, 어떤 역할을 하는지 패키지를 어떻게 나눠야 좋은 것인지 알아보겠습니다.

 


1. Spring Web Layer

 Spring에서 Web 계층은 사진과 같이 분류되는데, 특징과 역할을 알아보겠습니다.

 

1.1 Presentation Layer(Web Layer)

 프레젠테이션 계층브라우저 상의 웹 클라이언트의 요청, 응답을 처리하는 계층입니다. 서비스 계층과 데이터 엑세스 계층에서 발생하는 Exception(예외)를 처리, 인증 관리, 권한없는 사용자의 인가를 거부하는 역할을 합니다. 

 @Controller 애노테이션을 사용해 작성된 Controller 클래스, @Filter, 인터셉터, @ControllerAdivce가 모두 프레젠테이션 계층에 포함이 됩니다. 또한 데이터 처리 시 데이터 전송 객체만 처리하는 특징을 가집니다. 

 

1.2 Business Layer(Service Layer)

 서비스 계층은 애플리케이션의 비즈니스 로직과 관련된 도메인 모델의 적합성을 검증하고 트랜젝션을 관리하는 계층입니다. 프레젠테이션과 데이터 엑세스 계층 사이를 연결하여 두 계층이 직접적으로 통신하지 않도록 하며, @Service 인터페이스와 @Sevice 애노테이션을 사용해 작성된 Service 구현 클래스가 서비스 계층에 해당됩니다. 데이터 처리 시, 데이터 전송 객체를 메서드의 패러미터로 사용하고 도메인 모델 객체를 처리, 데이터 전송 객체만 웹 Layer로 반환할 수 있습니다. 

 

1.3 Data Access Layer(Repository Layer)

 데이터 엑세스 계층은 ORM(Mybatis, Hibernate)를 주로 사용하는 계층으로 DB에 data를 CRUD하는 계층입니다. DAO(DB에 접근하는 객체로 Repository라고도 함) 인터페이스와 @Repository 애노테이션을 사용해 작성된 DAO 구현 클래스가 이 계층에 해당됩니다. 데이터 처리 시, Entity를 메서드 패러미터로 가져올 수 있고 ENtity를 return할 수 있습니다. 

 

1.4 Domain Object(Domain Model)

 도메인 오브젝트는 전체 Life Cycle동안 변경되지 않는 객체로 Value Object로써 속성이나 사물을 설명하며, 도메인을 모든 사람이 동일한 관점에서 이해할 수 있도록 단순화 시킨 것입니다. 

1.5 DTOs

 DTO는 Data Transfer Object의 약자로 다른 계층 간 교환을 위한 객체입니다. DB에서 Data를 얻어 Service, Controller로 보낼 때 사용 하는 것으로 로직을 갖지 않고 순수 getter, setter 메서드를 가집니다. 종합하면 DTOs는 DTO 객체들이 존재하는 영역을 의미하게 되는 것이죠. 예를 들어 View Template 엔진에서 사용 될 객체 Repository Layer에서 결과로 넘겨준 객체를 DTO라고 합니다. 

 


2. Domain, DTO Class 분리

설계 시 Domain class DTO Class를 분리하는 이유는 View의 역할과 DB의 역할을 철저하게 분리하기 위함입니다.

Table과 매핑되는 Entity Class 변경 시 여러 클래스에 영향을 미치지만, VIew와 통신하는 DTO Class는 자주 변경되므로 분리시켜야 합니다. 

 


3. Business Logic 처리

 그렇다면 Business Logic은 어디서 처리해야 하는 걸까요? 결론부터 말하자면 Domain Model에서 처리해야 합니다. 

기존에 Service Layer에서 처리하던 방법을 트랜잭션 스크립트라고 하는데, 이 트랜잭션 스크립트의 단점은 프로젝트의 규모가 커지면서 하나의 서비스에 더 많은 Model을 읽어 로직이 구성될 수록 서비스의 복잡도가 높아지게 되는데, 이는 유지보수에 어려움이 있고 유연하지 못한 소프트웨어가 됩니다. 이러한 이유로 Service Layer에서는 트랜잭션과 도메인 간 순서 보장의 역할만 하게됩니다. 예시를 한번 살펴보겠습니다.

 

@Transactional
public Order cancelOrder(int orderId){
	//1) DB로 부터 주문정보, 결제정보 조회
	OrderDto 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) 각 테이블에 취소상태를 Update
	order.setStatus("CANCEL");
	ordersDao.update(order);

	billing.setStatus("CANCEL");;
	deliveryDao.update(billing);

	return order;
}

 위의 코드는 Service Layer에서 로직을 처리한 코드입니다. 보면 Service Layer가 무의미해지며 객체가 단순 데이터를 묶는 역할을 하는 것으로 보입니다. 하지만 Domain Model 패턴을 적용한 코드를 보겠습니다.

@Transactional
public Order cancelOrder(int orderId){
	//1)
	Orders order = orderRepository.findById(orderId);
	Billing billing = billingRepository.findByOrderId(orderId);
	Delivery delivery = deliveryRepository.findByOrderId(orderId);

	//2-3)
	delivery.cancel();

	//4)
	order.cancel();
	billing.cancel();

	return order;
}

 코드를 보게되면 order, billig, delivery가 각자 취소 이벤트를 처리하고, 서비스 메서드는 트랜잭션, 도메인 간 순서만을 보장해 주는 것을 볼 수 있습니다. 

 

 

 

 

 

 

참조

더보기

'Skills > Spring' 카테고리의 다른 글

Spring - DI & Spring Container  (0) 2022.08.31
Spring - 테스트 코드(TDD) 작성  (0) 2022.08.02
Spring - MockMvc를 이용한 HTTP 메시지 검증  (0) 2022.07.24
Spring - @RunWIth, @ExtendWith  (0) 2022.07.22
Spring - 의존관계 주입  (0) 2022.07.12