디자인패턴

파사드 패턴(Facade Pattern)

2료일 2025. 3. 25. 18:59

: 구조적 디자인 패턴 중 하나로, 복잡한 라이브러리, 프레임워크 또는 서브시스템을 간단한 인터페이스로 감싸주는 역할을 한다.

이로써 클라이언트가 시스템의 복잡성을 이해하지 않고도 필요한 기능을 쉽게 사용할 수 있게 해준다.

파사드? 프랑스어로 건물의 정면이라는 듯. 실제 건물에서 정면은 내부의 복잡한 구조를 가리고 단순한 외관만을 보여주는것처럼 소프트웨어에서도 복잡한 내부 구조를숨기고 단순한 인터페이스만 외부에 노출시키겟다~

 

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만 알면된다. 자연스레 서브들의 복잡한 결합도도 낮출 수 있다.

단점

제한된 유연성: 퍼사드가 제공하지 않는 서브시스템 기능은 클라이언트가 직접 접근해야함.

과도한 단순화: 너무 많은 책임을 퍼사드가 안으면 복잡

 

 

다른 패턴들과 비교

  1. 어댑터 패턴(Adapter Pattern):
    • 목적: 호환되지 않는 인터페이스를 클라이언트가 원하는 인터페이스로 변환.
    • 차이점: 퍼사드는 복잡한 서브시스템을 단순화하는 새로운 인터페이스를 제공하지만, 어댑터는 기존 클래스의 인터페이스를 변환하여 호환성을 보장.
    • 예시: 무신사에서 외부 결제 API(예: LegacyPaymentAPI)의 인터페이스(process(amount:))를 내부 시스템(PaymentProcessor)에 맞게 변환하려면 어댑터 사용. 반면, 주문 프로세스 전체를 단순화하려면 퍼사드 사용.
  2. 데코레이터 패턴(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