Design Pattern, Facade

2021. 12. 26. 02:00ETC/Design Patterns

Facade Pattern

 

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

- GoF Design Patterns

 

Facade Pattern은 서브시스템의 통일된 인터페이스에 대한 통합된 인터페이스제공합니다.

 

Facade Pattern에서는 시스템 결합과 사용이 용이하도록 관심사(위의 통합된 인터페이스)를 분리합니다.

내부 로직이 어떻게 구성되어 있는지 알지 못해도,

인터페이스를 통해 사용만 할 수 있도록 관심사를 묶는 것이 바로 Facade 패턴입니다.

 

https://www.javaguides.net/2018/07/facade-pattern-from-head-first-design-patterns.html

 

API 서비스라이브러리, 패키지도 Facade 패턴으로 이뤄어져 있으며, Facade 패턴을 응용하고 있다는 것을 모르고 있었을 뿐입니다. 이처럼 간단하고 일상적으로 많이 사용되는 패턴이기 때문에 개발자라면 누구나 한번쯤은 사용해보았을 만큼 간단합니다.

 

facade의 어원은 프랑스어로 건물의 정면이라는 의미를 가지는데, 관심사를 건물 내부로 숨기고 외부만 보일 수 있게 만드는 것으로 이해해도 좋을 것 같아요. 참고로, facade는 건물의 외관, 겉모습이라는 의미와 사전적으로는 ‘표면, 허울’로도 해석합니다.

 

일상에서의 예시를 들어보면, 은행에 갈 때 은행 내부 시스템을 몰라도 은행 업무를 처리할 수 있고, 은행원은 고객과 은행 전산 시스템을 이어주는 인터페이스 역할을 합니다. 퍼사드는 단순한 창구 역할의 은행원과 같죠.

 

퍼사드를 이용하면 객체(서브 세스템)의 내부 구조를 상세히 알 필요가 없기 때문에 시스템의 연결성과 종속성을 최소화하는 것을 목적으로 합니다.

 

다른 내용을 보기 전에 코드를 먼저 확인하는 것도 이해하는데 도움이 될 것 같습니다. 😉

 

 

 

왜 필요할까?

 

Facade Pattern은 협업과 대형 시스템을 개발하고 배포하는 데 자주 응용되는데요.

하나의 서비스를 여러명의 개발자와 공동으로 만드는 과정은 쉽지 않습니다. 또, 분리된 기능별 모듈을 하나로 합치는 과정에서 수많은 난관을 만나게 되죠. 대형 시스템을 효율적으로 개발하려면 기능을 모듈별로 분리하고 분리된 모듈을 공동으로 개발하는 것이 좋습니다. 오픈소스나 공개 API를 이용하는 것도 facade를 활용하는 좋은 방안이 될 수 있겠죠.

 

 

 

Facade의 구조

퍼사드 패턴은 메인 시스템과 서브 시스템 중간에 새로운 인터페이스 계층으로 위치합니다. 복잡한 서브 시스템의 동작을 하나로 묶어서 이를 실행할 수 있도록 제공하는 역할을 합니다. 이 구조는 시스템 간 강력한 결합 구조를 해결하며 의존성을 해결해줄 수 있습니다.

 

 

http://education.molssi.org/oop_and_design_patterns/12-Facade/index.html

 

 

코드는 분할된 모듈을 결합할 때 강력한 의존 관계를 갖는데, 코드의 의존성을 줄이고 느슨한 결합으로 변경할 수 있습니다.

 

또, 객체지향은 추상적인 개념을 도입해 객체를 캡슐화하는데, 캡슐화를 적용했다고 해서 객체 내 서브 시스템으로 접근할 수 없는 것은 아닙니다. 이런 점에서 은닉성은 떨어진다고 할 수도 있습니다.

 

퍼사드로 인해 새로운 계층이 하나 더 추가되면 관리할 클래스가 하나 더 생성된다는 단점이 있지만, 강력한 객체의 결합도를 낮추고 유연한 구조를 가질 수 있다는 장점이 있습니다.

 

Facade는 싱글턴 추상 팩토리singletone abstract factory 라고 불리기도 하는데요. 어떤 기능에 접근할 수 있는 단일화된 추상 클래스를 만듭니다.

 

 

 

최소 지식 원칙

Facade 패턴은 객체지향의 최소 지식 원칙이 적용되는 좋은 예가 됩니다.

 

최소 지식 원칙 principle of Least Knowledge은 다른 말로 데메테르의 법칙 Law of Demeter 이라고도 부릅니다.

 

최소 지식은 지식으로 장벽을 만들지 않아야 하며, 최소 지식만을 적용해 객체의 상호 작용을 설정하면 유지 보수가 용이해 질 수 있습니다. 복잡하게 얽혀 있는 서브 시스템의 어떤 부분을 수정할 경우 관련된 다른 부분도 같이 수정해야하는 경우가 있어서, 하나를 수정할 때 많은 연관 정보를 알고 있어야 제대로된 수정을 할 수 있습니다. 이 때, Facade 패턴을 사용해서 관심사를 묶어두면 최소 지식 원칙이 적용되도록 만들어질 수 있습니다.

 

 

최소 지식 객체

다음의 4가지 규칙만 따르면 최소 지식 원칙을 쉽게 적용할 수 있습니다.

 

  • 자기 자신만의 객체 사용
  • 메서드에 전달된 매개변수 사용
  • 메서드에서 생성된 객체 사용
  • 객체에 속하는 메서드 사용

 

예제 코드를 보면서 이해를 더해볼게요.

 

class Car {

    // ① 클래스의 구성 요소
    // 구성 요소의 메서드는 호출해도 됩니다.
    private Engine engine;

    public Car(String engine) {
        this.engine = engine;
    }

    public void start(Key key) {
        // ③ 새로운 객체 생성
        // 내부에서 생성된 객체의 메서드는 호출해도 됩니다.
        doors = new Doors();

        // ② 매개변수로 전달된 객체의 메서드는 호출해도 됨
        authorized = key.turns();

        if (authorized) {
            // ① 객체의 구성 요소의 메서드는 호출해도 됩니다.
            engine.start();

            // ④ 객체 내에 있는 메서드는 호출해도 됩니다.
            this.updateDashboardDisplay();

            // ③ 직접 생성하거나 인스턴스를 만든 객체의 메서드는 호출해도 됨
            doors.lock();
        }
    }

    public void updateDashboardDisplay() {
        // 생략
    }
}

 

 

Sample Code : Java

 

코드를 통해 확인하면 확실한 감을 잡을 수 있을 거에요.

Package1, Package2, Package3 객체를 묶는 예제로, 이 세개의 Package를 순차적으로 실행하는 것을 하나의 관심사라고 파악하시면 됩니다. Package1, Package2, Package3는 같는 내용으로 작성될 것이라, 하나만 적겠습니다.

 

아래 코드는 Github 링크에서 확인하실 수 있습니다.

 

 

SubSystems

// Package2, Package3 도 동일한 내용
public class Package1 {
    public Package1() {
        System.out.println("Package1 객체가 생성되었습니다.");
    }

    public void process() {
        System.out.println("Package1 작업을 진행합니다.");
    }
}

 

Facade를 이용하기 전, 직접적으로 Package들을 실행하는 예시를 먼저 확인해보겠습니다.

 

 

Facade 적용 전 Main

  package facade;

  public class Main {
      public static void main(String[] args) {
          Package1 obj1 = new Package1();
          obj1.process();

          Package2 obj2 = new Package2();
          obj2.process();

          Package3 obj3 = new Package3();
          obj3.process();
      }
  }

 

Facade

package facade;

public class Facade {
    private Package1 package1;
    private Package2 package2;
    private Package3 package3;

    public Facade() {
        this.package1 = new Package1();
        this.package2 = new Package2();
        this.package3 = new Package3();
    }

    public void processAll() {
        this.package1.process();
        this.package2.process();
        this.package3.process();
    }
}

 

 

Facade 적용 후 Main

package facade;

public class Main {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.processAll();
    }
}

 

 

정말 간단하죠 ?

Facade 패턴의 특징을 살펴보도록 할게요.

 

 

Facade 특징

 

✔️ 복잡성 해결

시스템을 구조화하면서 복잡성을 해결하는데 도움이 됩니다.

 

https://dzone.com/articles/facade-design-pattern-in-java

 

 

✔️ 서브 시스템 보호

서브 시스템의 구성 요소를 직접 호출하지 않으므로 잘못된 사용을 방지할 수 있습니다. 내부 구조와 외부 사용을 구분하기 때문에 서브 시스템을 업그레이드하는 경우에도 자유롭다는 장점이 있습니다.

 

✔️ 확장성

서비스를 유지 및 개발하게 되면 새로운 요청과 생각하지 못했던 오류가 발견되곤 하는데요. 안정적인 서비스를 유지하기 위해서는 지속적인 코드 변경이 필요합니다. 또, 시스템은 새로운 기능을 구현하기 위해 확장되며, 최적화 및 재사용을 위해 기존의 클래스가 단순해지기를 바라게 됩니다. 이 때 변화되는 코드를 Facade 형태로 제공하면 보다 쉽게 변경 및 확장할 수 있고, 상위 시스템에는 Facade를 이용하므로 서브 시스템이 변경돼도 큰 변화를 느낄 수 없습니다.

 

✔️ 결합도 감소

서브시스템과의 종속성이 강할 때 퍼사드 패턴을 사용하면 결합도를 낮출 수 있습니다.

 

✔️ 이식성

코드의 결합도를 약하게 하는 효과를 발생시킵니다. 코드 결합도가 약해지면서 다른 응용 프로그램에서도 코드를 쉽게 재사용할 수 있습니다. 이처럼, 다양한 응용 프로그램에서 서브 시스템을 공통적으로 사용할 수 있도록 이식성을 향상시킬 수 있습니다.

 

✔️ 공개 인터페이스

인터페이스를 활용한 캡슐화를 통해 공개할 부분과 공개하지 않을 부분을 결정하며, 필요한 행위만 노출하고 그 외의 코드를 비공개로 숨길 수 있습니다. 인터페이스를 제공함과 동시에 서브 시스템의 기능을 캡슐화함. 

 

 

 

관련 패턴

C- Creational Patterns  |  S - Structural Patterns  |  B - Behavioral Patterns

 

 

C: Singleton

파사드 패턴에서 서브 시스템의 접근을 단일화하기 위해 싱글턴 패턴을 응용합니다. 싱글턴을 통해 파사드 객체를 생성하는 방식을 적용하는 경우도 많습니다.

 

 

C: Abstract Factory

서브 시스템을 독립적으로 처리하기 위해 인터페이스를 제공하는데, 이때 인터페이스를 facade 패턴과 같이 적용하여 설계할 수도 있습니다. 추상 팩토리도 종속적인 서브 클래스를 감추는 효과를 가집니다.

 

 

S: Adapter

인터페이스를 제공한다는 측면에서 유사합니다.

하지만, 사용 용도가 다릅니다.

Adapter는 단순히 차이점을 해결하기 위한 인터페이스라면, Facade는 쉬운 접근과 동작을 위한 인터페이스를 제공합니다.

 

 

B: Mediator

복잡한 접근과 동작을 총제한다는 측면에서 중재자 패턴과 유사합니다.

하지만 파사드는 가시적이고 직접적으로 접근하는 반면, 중재자는 은밀하고 비강제적으로 접근합니다. 또, 중재자 패턴은 클래스 접근을 중계하는 기능을 수행하며 양방향성이지만, 파사드는 단방향이며 서브 시스템의 접근만 허용합니다.

 

 

 

그럼 지금까지 Facade Pattern에 대해 알아보았습니다.

오타나 잘못된 내용이 있다면 댓글로 남겨주세요!

감사합니다 ☺️ 

 

모든 Design Patterns 모아보기

 

Design Patterns

안녕하세요. GoF 디자인 패턴을 정리하고자 합니다. 디자인 패턴은 일주일 전부터 공부를 시작했는데, 스스로 설명하듯 적는게 익히는데 도움이 클 것같아 정말 오랜만에 시리즈로 포스팅하려

gngsn.tistory.com

 

'ETC > Design Patterns' 카테고리의 다른 글

Design Pattern, Factory Method  (0) 2022.01.03
Design Pattern, Template Method  (0) 2022.01.01
Design Pattern, Strategy  (0) 2021.12.29
Design Pattern, Builder  (1) 2021.12.29
Design Patterns, 제대로 이해하기  (1) 2021.12.26