파사드 패턴(Facade Pattern)
: 구조적 디자인 패턴 중 하나로, 복잡한 라이브러리, 프레임워크 또는 서브시스템을 간단한 인터페이스로 감싸주는 역할을 한다.
이로써 클라이언트가 시스템의 복잡성을 이해하지 않고도 필요한 기능을 쉽게 사용할 수 있게 해준다.
파사드? 프랑스어로 건물의 정면이라는 듯. 실제 건물에서 정면은 내부의 복잡한 구조를 가리고 단순한 외관만을 보여주는것처럼 소프트웨어에서도 복잡한 내부 구조를숨기고 단순한 인터페이스만 외부에 노출시키겟다~
ex) 무신사 옷 CS주문 넣는다고 하자. 상담원이 파사드 역할이다. 상담원이 매장의 시스템에 맞춰 해당하는 대응을 해주고 우리는 그냥 전화하는것만으로도 충분하다.
핵심 목적:
- 클라이언트가 서브시스템의 복잡한 내부 구조를 알 필요 없이 필요한 기능을 간편하게 사용.
- 서브시스템과 클라이언트 간 결합도를 낮춤.
- 최소지식원칙(Law of Demeter)을 준수하여 코드 유지보수성을 높임.
// 재고 관리 서브시스템
class InventorySystem {
func checkAvailability(productId: String) -> Bool {
print("재고 확인 중: \(productId)")
return true // 예시로 항상 재고가 있다고 가정
}
}
// 결제 처리 서브시스템
class PaymentSystem {
func processPayment(amount: Double) -> Bool {
print("결제 처리 중: \(amount)원")
return true // 결제 성공 가정
}
}
// 배송 준비 서브시스템
class ShippingSystem {
func prepareShipping(productId: String) {
print("배송 준비 중: \(productId)")
}
}
class OrderFacade {
private let inventory = InventorySystem()
private let payment = PaymentSystem()
private let shipping = ShippingSystem()
func placeOrder(productId: String, amount: Double) -> Bool {
// 1. 재고 확인
guard inventory.checkAvailability(productId: productId) else {
print("재고 부족으로 주문 실패")
return false
}
// 2. 결제 처리
guard payment.processPayment(amount: amount) else {
print("결제 실패")
return false
}
// 3. 배송 준비
shipping.prepareShipping(productId: productId)
print("주문 완료!")
return true
}
}
퍼사드 패턴의 구조
퍼사드 패턴은 다음과 같은 구성 요소로 이루어집니다:
- 퍼사드(Facade): 클라이언트가 호출하는 단순한 인터페이스. 서브시스템의 복잡한 로직을 조율.
- 서브시스템(Subsystems): 실제 작업을 수행하는 클래스들의 집합. 퍼사드가 이를 호출.
- 클라이언트(Client): 퍼사드를 통해 서브시스템에 접근.
언제 사용하나요?
퍼사드 패턴은 다음과 같은 상황에서 유용합니다:
- 복잡한 서브시스템(예: 데이터베이스, 네트워크, 하드웨어 제어)을 단순화하고 싶을 때.
- 클라이언트가 자주 사용하는 작업을 간단한 메서드로 통합하고 싶을 때.
- 서브시스템의 내부 구현을 캡슐화하여 변경 가능성을 줄이고 싶을 때.
이미 우리가 사용했던 UIKit에서는 많은 파사드 패턴을 사용하고 있다.
UIViewController: 뷰 계층 구조, 생명 주기 이벤트 등 복잡한 작업을 캡슐화
UIAlertController: 알림과 액션 시트의 복잡한 구성과 표시 로직 단순화
장점
낮은 결합도: Client가 서브들의 코드를 몰라도 된다 그저 Facade Object만 알면된다. 자연스레 서브들의 복잡한 결합도도 낮출 수 있다.
단점
제한된 유연성: 퍼사드가 제공하지 않는 서브시스템 기능은 클라이언트가 직접 접근해야함.
과도한 단순화: 너무 많은 책임을 퍼사드가 안으면 복잡
다른 패턴들과 비교
- 어댑터 패턴(Adapter Pattern):
- 목적: 호환되지 않는 인터페이스를 클라이언트가 원하는 인터페이스로 변환.
- 차이점: 퍼사드는 복잡한 서브시스템을 단순화하는 새로운 인터페이스를 제공하지만, 어댑터는 기존 클래스의 인터페이스를 변환하여 호환성을 보장.
- 예시: 무신사에서 외부 결제 API(예: LegacyPaymentAPI)의 인터페이스(process(amount:))를 내부 시스템(PaymentProcessor)에 맞게 변환하려면 어댑터 사용. 반면, 주문 프로세스 전체를 단순화하려면 퍼사드 사용.
- 데코레이터 패턴(Decorator Pattern):
- 목적: 기존 객체에 새로운 기능을 동적으로 추가.
- 차이점: 퍼사드는 기능 추가가 아니라 단순화를 목표로 하며, 서브시스템의 인터페이스를 통합.
- 예시: 주문 시 추가 할인 기능을 동적으로 붙이려면 데코레이터 사용. 주문 프로세스를 간단히 하려면 퍼사드.
참고자료
https://refactoring.guru/design-patterns/facade
Facade
Intent Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes. Problem Imagine that you must make your code work with a broad set of objects that belong to a sophisticated
refactoring.guru