-
Service에서 Service를 참조해야만하나? (with Facade 패턴)실전 개발해보기 2024. 2. 4. 11:26
이번 팀플을 해볼 때
내 도메인을 다른 도메인(팀원이)에서 가져다 쓸 것을 크게 고려하지 않고,
내 도메인에 대한 기능만 충실하면 된다고 착각해서,
Presentation(Controller)
|
Application(Service)
|
(Domain)
|
Infrastructure(Repository)
구조로 짰다.
쿠폰은 내가 다른 Service 을 가져다 쓸 부분은 없고 도메인 과 레포지토리 정도였다.
그러나 다른 도메인의 Service에서는 Coupon에 대한 기능이 필요했다.
다 짜고 보니까 다른 ProductService에서 CouponService 에 있는 기능이 필요했다.
그래서 몇가지 해결법을 정리해보았는데, 해결법중 뭐가 정답이다! 라는건 없다고 생각한다.
각 방법끼리의 트레이드 오프가 있고
현재 프로젝트에서 최적의 방법을 찾아가면 되는 것이다 !!
해결법 1
가장 단순한 방법으로 Service영역에서 Service 의존성을 받아서 사용할 수 있다.
MemberService 에 a() 메서드가 있고
TeamService에 a()메서드가 있을때,
트레이드 오프 1
Team의 a와 Member의 a 메서드를 하나의 트랜잭션으로 실행시키고 싶은 경우에는
결국 각각 작동하기 때문에 트랜잭션의 원자성(Atomicity)을 지키지 못한다.
물론 조회만 필요한 경우에는 위는 문제 삼지 않는다.
트레이드 오프 2
특정 서비스를 의존한다는것은 그 해당 서비스의 메서드를 사용하기 위해 가져오는 것인데,
이 때 의존하는 서비스가 내가 필요한 부분 외에 수많은 기능이 있다면,
필요 이상의 기능(의존하려는 Service)에 의존한다고 볼 수 있다.
또한 의존하는 서비스가 크면 클수록 순환 참조에 대한 문제도 조금 더 고려해봐야한다.
해결법 2
그럼 ProductController에서 여러 Service를 의존하고, 여러 Service에 대한 기능을 받아서 합치면 되지 않을까? 라는 생각을 했다.
트레이드 오프
조회의 경우에는 트랜잭션이 딱히 필요없지만
여러 로직(삽입+조회)을 수행해야 하는 경우에는 트랜잭션이 필수인데,
컨트롤러에서는 일반적으로 거는 트랜잭션 범위(service계층)를 벗어나기에 로직들을 하나로 묶을 수 없다.
참고로 트랜잭션이 필요하지 않은 경우에는 많진 않지만..
Service를 아예 사용하지 않고 Controller -> Repository를 불러오는 경우도 있다고 한다.
해결법 3
Facade 패턴 이용하기
찾아보니 스프링에서도 Service의 역할을 Business service facade라고 부르기도 하고있다.
스프링에서 Facade 패턴은 새로운 계층을 만든다는 의미보다 Service를 더 촘촘히 나눠서 구현하는 것이라 볼 수 있다.
Service 레이어에서 그대로 다른 도메인 Service를 의존하지 않고
조금은 다른 Service에 의존하는 것이라고 생각하면 된다.
나는 하나의 Service 가 너무 커지는 것 같아서,
1. Service를 다른 도메인에서 가져다 쓰는 것에 따라 분리를 하고,
2. Facade 패턴을 이용해서 해당 문제를 해결했다.
Reference
- https://www.inflearn.com/questions/30618/%EA%B6%81%EA%B8%88%ED%95%A9%EB%8B%88%EB%8B%A4
'실전 개발해보기' 카테고리의 다른 글
redis 캐시 적용기 ( 부하테스트를 곁들인... ) (0) 2024.03.21 동시성 문제 해결하기(1) - DB Lock (0) 2024.01.23 Bulk 데이터 삽입 최적화 - save() , saveAll() , batchUpdate() (4) 2023.12.09 clone과 fork 를 기반으로 git 이해하기 (0) 2023.08.29