서비스 레이어를 통해 주문 접수와 관련된 로직을 처리하면, 배달 시스템의 장애와 관계없이 사용자는 여전히 주문을 할 수 있다. 이처럼 서비스를 사용하면 트랜잭션 관리를 통해 유지 보수성을 높이고 독립적인 테스트가 가능하며, 다양한 컴포넌트(예: 리포지토리, 다른 서비스 등)를 주입받아 사용할 수 있다.
트랜잭션이란 일반적으로 여러 단계 또는 작업의 실행을 필요로 하는 단일 프로그램의 실행을 의미
📍Service Layer의 필요성
- 비즈니스 로직의 분리와 중앙화 : 도메인 객체간의 상호작용을 조정하고, Persistence Layer와 데이터를 주고 받으며, 한 기능 단위의 결과물을 Controller로 전달한다. 즉, Presentation Layer, Persistence Layer, Domain Model과 전부 상호 작용을 하며 핵심 비즈니스 로직을 처리하는 역할을 맡는다.
비즈니스 로직을 Controller나 Persistence Layer에서 직접 처리하는 경우, 코드가 복잡해지고 유지보수가 어려워진다. 이미 각자의 역할이 있는데 거기에 비즈니스 로직이 또 추가가 되기 때문이다. 그래서 서비스 계층을 도입함으로써 비즈니스 로직을 분리하고 중앙화 하여, 코드의 가독성과 유지보수성이 향상되고 개발 효율성을 높이게 된다. - 각 계층의 역할 명확화 : 바로 위의 역할에 연장되는 느낌인데, Controller는 사용자의 요청을 처리하고 응답을 생성하는 역할을, Persistence Layer는 DB와의 상호작용을 담당하는 역할을, Service Layer는 비즈니스 로직과 트랜잭션 관리를 수행하는 역할을 하게 된다. 이렇게 각 계층의 역할이 분명해지면 코드의 가독성과 유지보수성이 향상된다.
- 트랜잭션 관리 : 각 핵심 기능마다 데이터의 일관성과 무결성을 보장하기 위해 트랜잭션을 관리한다. 하나의 기능을 처리하기 위해 여러 Dao 혹은 Service를 통해 데이터를 다뤄야 할 때, 중간에 어떤 계기로 인해 기능이 중단되어 한 단위 기능의 원자성이 파괴되는 것을 예방하기 위함이다. 또한, 기능 단위로 트랜잭션을 관리할 수 있어서 트랜잭션의 경계를 더 명확히 할 수 있다.
Controller에서 관리하기엔, 각 트랜잭션의 단위가 너무 커지고 비즈니스 로직 처리와 트랜잭션 처리가 동시에 이루어지지 않아서 유지보수의 어려움이 생길 수 있다. 또한, Transactional은 AOP를 통해 구현되는데, Controller는 보통 인터페이스가 없다. AOP는 Dynamic proxy를 사용해서 인터페이스가 필요하기에, Controller에 Tracsantional을 적용하기엔 어려움이 따를 수 있다.
Persistence Layer에서 트랜잭션을 관리하기엔, 이 또한 비즈니스 로직과 데이터의 영속성과 관련된 작업이 혼재될 수 있다. 그리고 트랜잭션 범위의 한계가 너무 좁아져서 각각의 기능 단위를 관리하는 Service Layer에서 트랜잭션 처리를 하기 어렵게 된다. - 코드 재사용성 촉진 : 서비스 계층은 비즈니스 로직을 캡슐화하므로 애플리케이션의 여러 부분에서 코드 재사용성을 촉진한다. 예를 들어 여러 컨트롤러가 동일한 서비스를 사용하여 공통 작업을 수행하여 코드 중복을 줄일 수 있다.
📍Dao와 Service의 차이
DAO와 Service는 그 역할이 분명히 다르다. DAO는 단일 데이터 접근/갱신만 처리한다. Service는 여러 DAO를 호출하여 여러번의 데이터 접근/갱신을 하며 그렇게 읽은 데이터에 대한 비즈니스 로직을 수행하고, 그것을 하나의(혹은 여러개의) 트랜잭션으로 묶는다. 즉, Service가 트랜잭션 단위이다. 위와 같이 DAO와 Service가 완전히 동일해지는 경우도 분명히 발생한다. 하지만 그것은 해당 비즈니스 로직이 "단일 DB 접근"으로 끝나기 때문에 발생하는 것이다.
만약 DAO의 메소드 하나에 다중 DB접근 로직이 들어갔고, 서비스는 단순히 그 DAO메소드를 호출하는 통로 역할만 한다면 DAO측 모듈화가 제대로 안된 접근 방식일 가능성이 높다. 실제로 스프링에서는 iBatis관련 부분들이 DAO이다.
1. 계층 구조
- Presentation Layer : 사용자 인터페이스와 관련된 부분으로, 클라이언트의 요청을 처리하고 응답을 반환한다. 이 레이어에서 Controller는 사용자 요청을 받아 적절한 서비스 메서드를 호출한다.
- Business Layer (서비스 레이어): 비즈니스 로직을 처리하는 부분이다.
- Service Interface: 비즈니스 로직을 정의하는 인터페이스. 이 인터페이스를 통해 클라이언트는 비즈니스 기능을 호출할 수 있다.
public interface PdsService {
List<PdsVo> getPdsList(HashMap<String, Object> map);
}
- Service Implementations: 실제 비즈니스 로직이 구현된 클래스이다. DAO를 호출하여 데이터 처리 작업을 수행한다.
@Service
public class PdsServiceImpl implements PdsService{
@Autowired
private PdsMapper pdsMapper;
@Override
public List<PdsVo> getPdsList(HashMap<String, Object> map) {
//인터페이스 PdsService대신 서비스에 해당하는 코드를 넣게 해줌
List<PdsVo> pdsList = pdsMapper.getPdsList( map );
return pdsList;
}
}
- Data Access Layer (데이터 접근 레이어): 데이터베이스와의 상호작용을 처리하는 부분이다.
- DAO Interface: 데이터 접근 메서드를 정의하는 인터페이스. 데이터베이스와의 CRUD 작업을 수행할 수 있는 메서드를 포함한다.
- DAO Implementations: DAO 인터페이스를 구현한 클래스이다. 실제 데이터베이스와의 상호작용을 처리한다.
2. 서비스와 DAO의 관계
서비스 레이어:
클라이언트의 요청을 받아 비즈니스 로직을 수행한다.
DAO를 호출하여 필요한 데이터를 가져오거나 저장하는 등의 작업을 수행한다.
예를 들어, 사용자의 주문을 처리하는 서비스 메서드가 있을 경우, 이 메서드는 DAO를 통해 주문 정보를 데이터베이스에 저장하거나 조회한다.
DAO 레이어:
데이터베이스와의 직접적인 상호작용을 담당한다.
서비스 레이어에서 호출되어 데이터베이스에 접근하여 데이터를 읽거나 쓰는 역할을 한다.
서비스 레이어가 비즈니스 로직을 구현하는 동안, DAO는 데이터의 CRUD 작업을 처리하여, 데이터 접근을 추상화한다.
3. 데이터 흐름
사용자가 프레젠테이션 레이어에서 요청을 보내면, Controller가 이 요청을 받고 적절한 서비스 메서드를 호출한다.
서비스 메서드는 비즈니스 로직을 수행하며 필요에 따라 DAO를 호출하여 데이터베이스와 상호작용한다.
DAO는 데이터베이스에서 데이터를 조회하거나 저장한 후, 결과를 서비스 레이어로 반환한다.
서비스는 이 결과를 처리하여 클라이언트에게 응답을 보낸다.
4. 도메인 객체와 DTO
Domain Object (도메인 객체): 비즈니스 도메인 모델을 나타내며, 서비스와 DAO 간의 데이터 전송을 위한 형태이다.
VO (Value Object) / DTO (Data Transfer Object): 데이터 전송을 위한 객체로, 서비스와 DAO 간의 데이터 이동에 사용된다. 이는 데이터베이스로부터 조회한 데이터를 클라이언트에 전달할 때 유용하다.
'SPRING' 카테고리의 다른 글
[spring]파일 다운로드 (2) | 2024.11.07 |
---|---|
[Spring] 파일 업로드 및 저장 (0) | 2024.11.05 |
[Spring] 페이징(Pagination) (0) | 2024.10.20 |
[spring]회원정보 수정 - 비밀번호 체크하기 (0) | 2024.10.13 |
[spring] 회원가입 - 아이디 중복 체크하기 (0) | 2024.10.13 |