[Design Pattern] Facade Service

황성현·2025년 9월 16일

Design Pattern

목록 보기
1/1

찾아보게된 배경

실제 Legacy 환경의 현업에서 일한지 대략 1년 쯤 된 지금...
어느정도 기능의 측면에서 패키지 구조가 분리되어 있지만, 패키지 안에 단일 Controller, Service, Repository로 구성된 곳에서 일하다보니 일단 하나의 서비스 클래스 파일에서 소스가 3~40000줄은 기본으로 넘는다.
여기서 특정 기능의 추가나 디버깅, 혹은 메서드 수정을 할 때 A라는 도메인에서 쓰여야할 private한 메서드가 기능적으로 어느정도 비슷해서 B,C,D 와 같은 로직에서도 사용하고.. 뭐 하나를 고치려고 찾는 것 조차도 힘들다.
그리고 실제 필요한 기능이 있어서 구현했더니 , 나중가서 보니 23000번째 라인에서 구현이 되어있다던가...

  • 이러한 문제를 해결할 만한 패턴이 있나 찾아보던 중 Facade Service를 발견!

What is Facade Service?

  • 여러 세부 서비스들을 한 번에 묶어서, 외부에서 보기에 단일한 인터페이스를 제공하는 것
  • 이를 위해서는 각각의 순수 도메인에 관련하여 비즈니스 로직을 구현한 서비스가 존재해야함
    => 이를 이용해 특정 기능을 구현할 때 해당 도메인 서비스( "ModuleService" )들을 조합하여 사용!
  • 즉 일종의 오케스트레이터 역할임.
  • 각 도메인 서비스는 본인 책임의 로직만 신경 쓰고, Facade에서 이들을 통합하여 사용하기 편하게 하면서 트랜잭션 경계나 순서 제어같은 흐름 제어를 할 수 있음.

Multi-Module Architecture과 연계하면?

ex. OrderFacadeService가 주문 + 결제 + 포인트를 함께 처리
즉 3개의 도메인의 협력이 필요할 때 해당 Facade에서 의존하고, 각각의 도메인 서비스는 순수하게 유지할 수 있음 (기존 단순 service + repo 구조는, 반드시 service끼리의 의존 혹은 service에서 필요한 repo에 의존을 걸어 데이터를 가져와야해서 경계가 무너짐) / @Transcation 흐름 묶기도 편함

예시코드 :

@Service
@RequiredArgsConstructor
public class OrderFacadeService {
    private final OrderService orderService;
    private final MemberService memberService; 
    private final PaymentService paymentService; // 
    //해당 Service들은 만약 다형성이 필요해 구현체를 갈아끼울 가능성이 있다면 interface     
    //그 외에는 구체 클래스로 구현하여 관리포인트 down
    

    @Transactional
    public OrderResultDto placeOrder(OrderRequestDto request) {
        Member member = memberService.findById(request.getMemberId());
        Order order = orderService.createOrder(member, request.getItems());
        paymentService.pay(order);
        return OrderResultDto.of(order);
    }
}
  • +DDD
  • domain: 순수 비즈니스 로직, 규칙, 불변식 관리
  • application: 유스케이스 조율 (Facade처럼 orchestrator 역할) + @
  • infrastructure: JPA, DB, 외부 API 연동

0개의 댓글