[디자인 패턴] 퍼사드 패턴(Facade Pattern)

이재민·2024년 4월 21일
0

디자인패턴

목록 보기
3/3

Facade Pattern

퍼사드 패턴은 복잡한 서브 클래스들의 강결합을 낮춰줄 수 있고 클라이언트에게 간편한 인터페이스를 제공할 수 있는 구조 패턴이다.

저번 전략 패턴을 이어 퍼사드 패턴에 대한 포스팅을 하게 되었다.
퍼사드 패턴 또한 전략 패턴 못지 않게 실무에서 굉장히 유용하게 사용하고 있는 디자인 패턴이다.

퍼사드 패턴을 사용하기 이전에는 비즈니스 로직이 다른 구현 세부 내용과 밀접하게 결합되어 코드를 이해하고 유지보수하기 어려웠었다.
퍼사드 패턴을 통해 복잡한 서브 시스템을 알 필요없이 클라이언트 입장에서는 퍼사드에서 제공하는 단순한 인터페이스를 이용하기만 하면 된다.

Facade 패턴 구조

  • Client: 기존 서브시스템들을 직접 접근, 조합하여 사용하는 대신 Facade에서 제공하는 인터페이스를 사용한다.
  • Facade: 서비스 레이어보다 한 단계 높은 레이어에서 단순한 인터페이스를 구성한다. 기존 Client는 서비스 레이어에 있는 여러 서브시스템과 긴밀하게 연결되어 있었지만, 한 단계 높은 레이어에서 간단한 인터페이스를 제공하는 Faacade를 사용한다.
  • Additional Facade: 퍼사드가 반드시 한개만 존재해야 한다는 규칙은 없다. 응집에 따라 분리해야 한다면 얼마든지 추가적인 퍼사드를 제공할 수 있다. 이러한 추가적인 퍼사드는 클라이언트에서 직접 접근하여 사용할 수도 있고, 다른 퍼사드에서도 사용할 수 있다.
  • SubSystem: 여러 객체 혹은 라이브러리

Facade 패턴 사용 시기

  1. 시스템이 복잡하여 추가 요구사항이 늘어나게 되면 유지보수가 힘들어질 경우
  2. 복잡한 시스템을 사용하는 클라이언트가 늘어날 경우
  3. 의존성 낮은 시스템을 구성하기 위해

Facade 패턴 장/단점

장점

  • 클라이언트는 복잡한 서브시스템들을 조합하기보다는 간단한 인터페이스 사용으로 부담이 적어진다.
  • 복잡한 코드를 감추어 Facade만으로 시스템을 이해하고 사용할 수 있다.

단점

  • Facade 자체가 서브시스템의 의존성을 가지게 되는 것이지 의존성 자체를 피할 수는 없다.

예제

응모 참여자들을 추첨하여 혜택을 지급하고 앱 푸시를 보내는 요구사항이 있다고 구현하려고 한다.
코드들이 궁금하시다면 예제코드를 참고해주세요.

Facade 패턴을 사용하지 않은 Client

public class Client {

    public static void main(String[] args) {
        // 이벤트 조회
        Long eventId = 1L;
        EventSearch eventSearch = new EventSearch();
        RaffleEvent event = eventSearch.searchEvent(eventId);

        // 당첨자 추첨
        EntrantRaffle entrantRaffle = new EntrantRaffle();
        entrantRaffle.raffle();

        // 혜택 지급
        if (event.isCouponBenefitEvent()) {
            CouponDispenser couponDispenser = new CouponDispenser();
            couponDispenser.giveCoupon();
        } else if (event.isPointBenefitEvent()) {
            PointDispenser pointDispenser = new PointDispenser();
            pointDispenser.givePoint();
        }

        // 앱 푸시 발송
        AppPush appPush = new AppPush();
        appPush.sendPush();
    }
}

위 예제 코드를 확인해보면 클라이언트는 다양한 서브 클래스들과 많은 연관관계를 맺고 있다. 예제 코드는 편의상 역할 분리를 제대로 하지 않았지만, 제대로 분리된 역할을 의존하게 된다면 아래 이미지처럼 의존성을 갖게 될 것이다.

예제코드에는 충분히 다양한 요구사항이 추가될 수 있을 것이다. 그렇다면 Client는 더욱 많은 의존성을 갖게 될 것이다.

Facade 패턴을 이용한 Client

public class UsingFacadeClient {

    public static void main(String[] args) {
        // 이벤트 조회
        Long eventId = 1L;
        EventSearch eventSearch = new EventSearch();
        RaffleEvent event = eventSearch.searchEvent(eventId);

        // Facade를 이용한 이벤트 처리
        Facade facade = new Facade();
        facade.raffleProcess(event);
    }
}
public class Facade {

    public void raffleProcess(RaffleEvent event) {
        // 당첨자 추첨
        EntrantRaffle entrantRaffle = new EntrantRaffle();
        entrantRaffle.raffle();

        // 혜택 지급
        if (event.isCouponBenefitEvent()) {
            CouponDispenser couponDispenser = new CouponDispenser();
            couponDispenser.giveCoupon();
        } else if (event.isPointBenefitEvent()) {
            PointDispenser pointDispenser = new PointDispenser();
            pointDispenser.givePoint();
        }

        // 앱 푸시 발송
        AppPush appPush = new AppPush();
        appPush.sendPush();
    }
}

앞서 Facade 패턴을 설명할때 언급했듯이 한 단계 높은 레이어에서 Facade를 제공한다고 했다.
이로써 Facade 패턴을 이용한 Client는 여러 의존성에 얽히지 않고 간단한 인터페이스(API)를 제공받아 사용하게 되었다.

마치며

퍼사드 패턴을 적용하여 Client의 코드는 매우 심플해졌다. 퍼사드의 핵심은 심플한 인터페이스를 제공하여 동료 개발자에게 유지보수성을 높여줄 수도 있고, 가독성 높은 코드를 제공할 수 있게 된다.

퍼사드는 하위 시스템을 캡슐화하는 것은 아니다. 단순히 복잡하게 얽혀 있는 서브시스템을 간단한 인터페이스를 제공할 뿐이다.

더욱 복잡한 요구사항 및 시스템도 이러한 퍼사드 패턴을 유용하게 이용한다면 유지보수성 높은 코드를 구성할 수 있다고 생각한다.

profile
문제 해결과 개선 과제를 수행하며 성장을 추구하는 것을 좋아합니다.

0개의 댓글