정보보안-이론/XX에 대하여

[디자인 패턴] (GoF 구조패턴) Facade Pattern에 대하여

리덕토 2025. 7. 8. 17:42

안녕하세요! GoF 디자인 패턴 연재, 이번 시간에는 구조 패턴(Structural Patterns)의 한 종류로, 복잡한 서브시스템을 더 쉽게 사용할 수 있도록 간단한 통합 인터페이스를 제공하는 퍼사드(Facade) 패턴에 대해 알아보겠습니다.


정의

퍼사드(Facade)는 프랑스어로 '건물의 정면'을 의미합니다. 퍼사드 패턴은 이 이름처럼, 복잡하게 얽혀있는 서브시스템들의 정면에 서서, 간단하고 통일된 하나의 창구(인터페이스)를 제공하는 패턴입니다. 클라이언트는 이 퍼사드 객체만 상대하면 되므로, 내부의 복잡한 구조를 알 필요가 없습니다.

 

가장 좋은 예는 '홈시어터' 시스템입니다. 영화 한 편을 보기 위해 우리는 앰프, DVD 플레이어, 프로젝터, 스크린, 조명 등 수많은 기기를 조작해야 합니다. "앰프 켜기 -> DVD 플레이어 켜기 -> DVD 넣기 -> 프로젝터 켜기 -> 스크린 내리기 -> 조명 어둡게 하기" 와 같은 복잡한 절차를 매번 거쳐야 하죠. 이때 '홈시어터 통합 리모컨'이 있다면 어떨까요? "영화 보기" 버튼 하나만 누르면, 이 모든 과정이 알아서 착착 진행됩니다. 여기서 '홈시어터 통합 리모컨'이 바로 퍼사드 역할을 합니다. 클라이언트(사용자)는 복잡한 내부 동작을 전혀 몰라도, "영화 보기"라는 단순한 인터페이스를 통해 원하는 결과를 얻을 수 있습니다.

 

퍼사드 패턴의 구조는 매우 직관적입니다.

  • Facade (퍼사드): 서브시스템의 복잡한 기능들을 조합하여 클라이언트가 사용하기 쉬운 상위 수준의 인터페이스를 제공합니다. 클라이언트의 요청을 받으면, 자신이 알고 있는 여러 서브시스템 객체들에게 작업을 위임합니다.
  • Subsystem Classes (서브시스템 클래스들): 실제 기능을 구현하는 여러 클래스의 집합입니다. 이들은 퍼사드 객체의 존재를 전혀 알지 못합니다.
  • Client (클라이언트): Facade 객체를 통해 서브시스템의 기능들을 사용합니다.

사용예시

 

앞서 설명한 홈시어터 예제를 자바(Java) 코드로 구현해 보겠습니다.

1. 서브시스템 (Subsystem) 클래스들 정의

홈시어터를 구성하는 각 기기들을 클래스로 정의합니다.

// Subsystem A
class Amplifier {
    public void on() { System.out.println("앰프가 켜졌습니다."); }
    public void setDvd() { System.out.println("앰프를 DVD 모드로 설정합니다."); }
    public void setSurroundSound() { System.out.println("앰프를 서라운드 사운드로 설정합니다."); }
    public void setVolume(int level) { System.out.println("볼륨을 " + level + "로 설정합니다."); }
    public void off() { System.out.println("앰프가 꺼졌습니다."); }
}

// Subsystem B
class DvdPlayer {
    public void on() { System.out.println("DVD 플레이어가 켜졌습니다."); }
    public void play(String movie) { System.out.println("\"" + movie + "\"를 재생합니다."); }
    public void off() { System.out.println("DVD 플레이어가 꺼졌습니다."); }
}

// Subsystem C
class Projector {
    public void on() { System.out.println("프로젝터가 켜졌습니다."); }
    public void wideScreenMode() { System.out.println("프로젝터를 와이드 스크린 모드로 설정합니다."); }
    public void off() { System.out.println("프로젝터가 꺼졌습니다."); }
}

// ... 그 외 Screen, TheaterLights 등 다른 서브시스템 클래스들 ...

2. 퍼사드 (Facade) 클래스 구현

복잡한 과정을 하나로 묶어주는 HomeTheaterFacade를 정의합니다.

// Facade 클래스
public class HomeTheaterFacade {
    // 서브시스템 객체들을 구성(composition)으로 가짐
    private Amplifier amp;
    private DvdPlayer dvd;
    private Projector projector;

    public HomeTheaterFacade(Amplifier amp, DvdPlayer dvd, Projector projector) {
        this.amp = amp;
        this.dvd = dvd;
        this.projector = projector;
    }

    // 복잡한 과정을 하나로 묶어 단순한 인터페이스를 제공
    public void watchMovie(String movie) {
        System.out.println("=== 영화 볼 준비를 시작합니다... ===");
        projector.on();
        projector.wideScreenMode();
        amp.on();
        amp.setDvd();
        amp.setSurroundSound();
        amp.setVolume(5);
        dvd.on();
        dvd.play(movie);
    }

    public void endMovie() {
        System.out.println("\n=== 홈시어터를 끕니다... ===");
        dvd.off();
        amp.off();
        projector.off();
    }
}

3. 클라이언트 (Client) 코드

클라이언트는 퍼사드 객체만 사용하여 간단하게 홈시어터를 조작합니다.

public class Client {
    public static void main(String[] args) {
        // 1. 필요한 서브시스템 객체들 생성
        Amplifier amp = new Amplifier();
        DvdPlayer dvd = new DvdPlayer();
        Projector projector = new Projector();

        // 2. 퍼사드 객체 생성 시 서브시스템들을 전달
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, dvd, projector);

        // 3. 클라이언트는 단순한 메서드만 호출
        homeTheater.watchMovie("인셉션");
        homeTheater.endMovie();
    }
}


결론

그럼 퍼사드 패턴은 언제 사용하면 좋을까요?

 

  • 복잡한 서브시스템에 대해 간단한 인터페이스를 제공하고 싶을 때: 클라이언트와 서브시스템 간의 의존성을 줄여 결합도를 낮출 수 있습니다.
  • 서브시스템을 계층적으로 구성해야 할 때: 각 계층은 퍼사드를 통해 다음 하위 계층과 통신하도록 구성할 수 있습니다.
  • 레거시 시스템을 리팩토링할 때: 기존의 복잡한 코드를 직접 건드리지 않고, 퍼사드를 통해 새로운 인터페이스를 제공하여 점진적으로 시스템을 개선할 수 있습니다.

Client에게 사편의성을 줄 수 있는 패턴이지만 다음과 같은 항목을 조심해야합니다

  • 퍼사드 객체가 모든 책임을 지는 만능 객체가 될 수 있음: 너무 많은 기능을 퍼사드에 추가하면, 퍼사드 자체가 또 다른 복잡한 서브시스템이 되어버릴 수 있습니다. (God Object 안티 패턴)
  • 불필요한 의존성: 클라이언트가 서브시스템의 일부 기능만 필요로 하더라도, 퍼사드를 통해 전체 서브시스템과 간접적으로 의존하게 될 수 있습니다.

퍼사드 패턴은 복잡함을 감추고 단순함을 드러내는 매우 실용적인 패턴입니다. 잘 설계된 퍼사드는 시스템의 사용성을 크게 향상시키고, 유지보수를 용이하게 만들어줍니다. 다음 시간에는 마지막 구조패턴, Proxy 패턴에 대해서 알아보겠습니다.