brunch

제10장: 퍼사드 패턴

복잡한 시스템을 위한 단순한 창구

by jeromeNa

집에서 영화를 보기 위해 어떤 과정을 거치는지 생각해 보세요. TV를 켜고, 홈시어터 시스템을 작동시키고, 불을 어둡게 하고, 팝콘을 준비하고… 여러 단계가 필요합니다. 이런 복잡한 과정을 “영화 모드”버튼 하나로 해결할 수 있다면 얼마나 편리할까요? 퍼사드 패턴은 바로 이런 아이디어에서 출발합니다.


대표적으로 패스트푸드점이 있습니다. 단품 메뉴도 있지만, 세트메뉴에는 햄버거, 감자튀김, 음료가 포함되어 있습니다. 가령 ‘세트 1번’을 주문하면 주방에서는 햄버거 조리, 감자튀김 준비, 음료 제공 등 여러 복잡한 과정이 동시에 진행됩니다. 주문 시스템은 고객에게 복잡한 주방 프로세스를 숨기고 단순한 메뉴 선택만으로 전체 과정을 시작할 수 있게 합니다.


퍼사드(Facade)는 건물의 장면 또는 외관을 의미합니다. 복잡한 서브시스템에 대한 간단하고 통합된 인터페이스를 제공하여 사용하기 쉽게 만드는 구조적 패턴입니다.


1970년대 초 데이비드 파나스(David Parnas)의 모듈화 설계 연구에서 복잡한 시스템을 단순한 인터페이스로 감싸는 소프트웨어 설계의 기본 원칙 중 하나인 ‘정보 은닉(information hiding)’과 ‘캡슐화(encapsulation)’의 자연스러운 확장을 중요하게 다루어졌으며, 객체지향 프로그래밍이 발전함에 따라 더욱 체계화되었습니다.


1980년대 초반부터 중반까지 개발된 여러 사용자 인터페이스 프레임워크와 API에서도 퍼사드 패턴과 유사한 접근법이 사용되었습니다. 특히 애플의 매킨토시 프로그래밍 환경에서 복잡한 그래픽 기능을 단순화된 API로 제공하는 방식은 퍼사드 패턴의 기초 사례로 볼 수 있습니다.


이러한 발전으로 1994년 GOF에 의해 공식적으로 퍼사드 디자인 패턴으로 문서화되었습니다.

퍼사드 패턴의 구조는 클라이언트에게 단순화된 인터페이스를 제공하는 퍼사드(Facade), 다양한 기능을 수행하는 복잡한 시스템의 여러 서브클래스들로 구성됩니다.


// 서브시스템 클래스들
// TV 클래스
class TV {
public void turnOn() {
System.out.println("TV 켜기");
}

public void turnOff() {
System.out.println("TV 끄기");
}

public void setInput(String input) {
System.out.println("TV 입력을 " + input + "으로 설정");
}
}

// 오디오 클래스
class AudioSystem {
public void turnOn() {
System.out.println("오디오 시스템 켜기");
}

public void turnOff() {
System.out.println("오디오 시스템 끄기");
}

public void setVolume(int level) {
System.out.println("볼륨을 " + level + "로 설정");
}

public void setSurroundSound() {
System.out.println("서라운드 사운드 설정");
}
}

// 조명 클래스
class Lights {
public void dim(int level) {
System.out.println("조명을 " + level + "% 밝기로 설정");
}

public void brighten() {
System.out.println("조명 밝게 하기");
}
}

// 영화 클래스
class StreamingPlayer {
public void turnOn() {
System.out.println("스트리밍 플레이어 켜기");
}

public void turnOff() {
System.out.println("스트리밍 플레이어 끄기");
}

public void playMovie(String movie) {
System.out.println(movie + " 재생");
}

public void stopMovie() {
System.out.println("영화 정지");
}
}

// 팝콘 클래스
class Popcorn {
public void start() {
System.out.println("팝콘 기계 시작");
}

public void stop() {
System.out.println("팝콘 기계 정지");
}
}

// 퍼사드
class HomeTheaterFacade {
// 각 서브클래스들을 정의합니다.
private TV tv;
private AudioSystem audio;
private Lights lights;
private StreamingPlayer player;
private Popcorn popcorn;

public HomeTheaterFacade(TV tv, AudioSystem audio, Lights lights,
StreamingPlayer player, Popcorn popcorn) {
this.tv = tv;
this.audio = audio;
this.lights = lights;
this.player = player;
this.popcorn = popcorn;
}

// 복잡한 과정을 단순화한 메서드
public void watchMovie(String movie) {
System.out.println("영화 감상 준비...");
popcorn.start();
lights.dim(10);
tv.turnOn();
tv.setInput("스트리밍");
audio.turnOn();
audio.setSurroundSound();
audio.setVolume(5);
player.turnOn();
player.playMovie(movie);
System.out.println("영화 감상 시작!");
}

public void endMovie() {
System.out.println("홈시어터 종료 중...");
popcorn.stop();
lights.brighten();
player.stopMovie();
player.turnOff();
audio.turnOff();
tv.turnOff();
System.out.println("홈시어터 종료!");
}
}


이렇게 정의된 클래스들과 퍼사드 클래스는 아래와 코드와 같이 사용됩니다.


public class Main {
public static void main(String[] args) {
// 서브시스템 컴포넌트 생성
TV tv = new TV();
AudioSystem audio = new AudioSystem();
Lights lights = new Lights();
StreamingPlayer player = new StreamingPlayer();
Popcorn popcorn = new Popcorn();

// 퍼사드 생성
HomeTheaterFacade homeTheater = new HomeTheaterFacade(tv, audio, lights, player, popcorn);

// 단순화된 인터페이스 사용
homeTheater.watchMovie("인셉션");
System.out.println("\n--- 영화 감상 중 ---\n");
homeTheater.endMovie();
}
}


이를 실행하면..


영화 감상 준비...
팝콘 기계 시작
조명을 10% 밝기로 설정
TV 켜기
TV 입력을 스트리밍으로 설정
오디오 시스템 켜기
서라운드 사운드 설정
볼륨을 5로 설정
스트리밍 플레이어 켜기
인셉션 재생
영화 감상 시작!

--- 영화 감상 중 ---

홈시어터 종료 중...
팝콘 기계 정지
조명 밝게 하기
영화 정지
스트리밍 플레이어 끄기
오디오 시스템 끄기
TV 끄기
홈시어터 종료!


각 서브 클래스들 (TV, 오디오, 영화, 조명, 팝콘 등)을 만들어 퍼사드를 생성한 후 homeTheater.watchMovie("인셉션");로 단순히 watchMovie만 실행하면 모든 것이 자동으로 수행됩니다.


퍼사드 패턴은 ‘최소 지식 원칙(Principle of least knowledge)’ 또는 ‘디미터의 법칙(Law of Demeter)’을 잘 구현한 예입니다. - 디미터(Demeter)는 데메테르라는 그리스 신화에서 농업, 수확, 곡물을 관장하는 여신입니다. 하지만 디미터의 법칙은 1987년 미국 노스이스턴 대학교에서 진행된 소프트웨어 개발 프로젝트의 이름에서 유래했습니다. 프로젝트 이름을 ‘디미터’로 지은 이유는 그 당시 연구팀이 있던 건물 근처에 ‘디미터 카페’가 있었기 때문이라고 합니다. 연구자들이 자주 들르던 이 카페의 이름을 따서 프로젝트이름을 정했고, 결과적으로 이 프로젝트에서 발견된 객체지향 설계 원칙이 ‘디미터의 법칙’으로 명명되었습니다.-


이 원칙은 객체가 자신과 직접 관련된 객체와만 상호작용해야 한다는 것을 의미합니다. 즉, 퍼사드는 클라이언트가 서브시스템의 모든 컴포넌트를 알 필요 없이 하나의 인터페이스만 알면 된다는 말입니다.


간단히 말해, 퍼사드 패턴은 복잡한 현실을 단순하게 보이도록 해주는 창문과 같습니다. 건물의 외관이 내부의 복잡한 구조를 가리듯, 이 패턴은 시스템의 복잡성을 감추고 사용하기 쉬운 인터페이스를 제공합니다.


실생활의 대부분이 퍼사드 패턴과도 같은 방식입니다. 간단한 인터페이스를 통해 복잡한 시스템을 실행하는 방식이 이에 해당합니다. 흔히 사용하는 스마트폰, 앱, 자동차 운전, 대중교통 이용을 위한 카드, 키오스크 등이 있습니다.


퍼사드 패턴은 ‘단순함은 최고의 정교함이다’라는 원칙을 실현하는 방식으로, 현대 사회의 복잡한 시스템과 서비스를 보다 접근 가능하고 사용하기 쉽게 만듭니다.

keyword