
때는 내가 상품(Product)과 주문(Order) 도메인을 한창 작성하고 있을 때였다.
사실, 그때의 내 ProductService와 OrderService는 거대한 쓰레기통이나 다름없었다. 적어도 'Facade(파사드)'를 만나기 전까지는 말이다.
그 당시까지 내 머릿속이나 코드 사전에는 'Facade'라는 말은 존재하지도 않았다. 내 서비스 클래스는 다른 서비스들까지 포함해서, 하나의 서비스 클래스에 최소 3개 이상의 서비스가 주입되어 있었다. 하지만 이 구조가 왜 잘못됐는지 전혀 몰랐다. 사실 그렇게밖에 짤 수 없다고 생각했다.
특히 내가 쓰던 레이어드 아키텍처에서 ProductService와 OrderService는 단연 가장 무거웠다. 마치 온갖 쓰레기가 가득 차 넘쳐 흐르는 쓰레기통처럼.
@Component
@RequiredArgsConstructor
public class ProductService {
private final ProductRepository productRepository;
private final OrderService orderService;
private final UserService userService;
private final PointService pointService;
}
처음엔 이 구조가 너무나 당연하게 느껴졌다. "이거 말고 방법이 있어? 당연히 상품을 주문할 땐 사용자 정보도 필요하고, 포인트 관리도 해야 하고, 주문 정보도 필요하지 않아?"라고 생각했다. 그때는 이게 최선이라고 믿었다.
하지만 이런 대환장 파티 같은 구조를 구원해줄 존재가 나타났다. 그게 바로 'Facade'였다.
파사드는 간단히 말해 복잡한 여러 하위 시스템을 감싸고, 이를 하나의 간단한 인터페이스로 제공하는 객체다. 복잡한 로직이나 여러 서비스의 조합을 하나의 클래스로 묶어 외부에서 단순하게 사용할 수 있도록 해준다.
파사드를 쓰면 서비스 간의 의존성을 줄이고, 각 서비스는 자신의 역할에만 집중할 수 있게 된다. 예를 들어, 제품 등록 하나만 봐도 상품, 주문, 사용자, 포인트 등 다양한 서비스가 얽혀있는데, 이런 복잡한 흐름을 깔끔하게 관리해준다.
기존 서비스에서 조합하던 부분을 파사드 클래스로 옮기면 된다. 예를 들어, 아래처럼 ProductFacade를 만들어 사용한다.
@Component
@RequiredArgsConstructor
public class ProductFacade {
private final ProductService productService;
private final OrderService orderService;
private final UserService userService;
private final PointService pointService;
@Transactional
public void registerProduct(RegisterProductRequest request) {
User user = userService.findUser(request.getUserId());
Product product = productService.createProduct(request.getProductDetails());
Order order = orderService.createOrder(user, product);
pointService.updateUserPoints(user, product.getPoints());
}
}
컨트롤러는 이제 더는 여러 서비스를 관리하지 않아도 된다. 오직 파사드만 호출하면 된다.
겉으로 보면 단순히 클래스 위치의 차이 같아 보인다. 하지만 이 차이는 단순히 위치만 바꾸는 것 이상의 의미를 가진다.
서비스는 원래 자신의 도메인 로직(예: 상품 정보 관리, 사용자 정보 관리)에만 집중해야 한다. 반면 파사드는 그런 서비스의 순서를 정하고 조합하는, 말 그대로 오케스트라의 지휘자 역할을 한다. 따라서 파사드를 두면 서비스 간의 의존성이 사라지고, 각각의 서비스는 자신의 책임과 규칙에만 집중할 수 있게 된다.
또한, 서비스 클래스는 더 가볍고 테스트하기 쉬워지며, 유지보수가 용이해진다.
파사드를 너무 많이 쓰면 결국 또 다른 형태의 복잡성을 초래할 수 있다. 따라서 파사드는 다음 원칙을 지키면 좋다.
서비스가 복잡하게 엮이는 유즈케이스를 관리할 때 사용한다.
하나의 파사드 클래스가 너무 방대해지지 않도록 한다. 필요하면 세부적인 유즈케이스로 나누어 작은 파사드를 여러 개 만든다.
파사드는 단순히 서비스의 순서와 조합만 담당하며, 절대 도메인 규칙을 직접 구현하지 않는다.
파사드 만큼은 절차지향을 행해야 한다.
파사드의 존재 이유는 명확하다. 마치 음악 공연을 생각해 보자. 무대 뒤에서 음향 엔지니어(파사드)는 다양한 악기와 마이크(서비스)를 직접 연주하거나 조작하지 않는다. 각 연주자와 가수는 자신의 연주와 노래에만 집중하고, 음향 엔지니어는 이 소리들이 최상의 조화를 이루도록 볼륨과 균형만 조정한다.
서비스는 각자의 도메인에서 자신이 맡은 본연의 역할만 수행하고, 파사드는 이 서비스들이 조화롭게 협력할 수 있도록 조율만 한다. 바로 이런 이유로 파사드는 필수다. 서비스는 서비스를, 파사드는 협력을 담당하는, 명확한 역할 구분이야말로 좋은 설계의 시작이지 않을까?