퍼사드(Facade) 패턴은 복잡한 서브시스템에 단순한 인터페이스를 제공하여 서브시스템을 쉽게 사용할 수 있도록 하는 구조적 디자인 패턴이다. 이 패턴은 클라이언트가 복잡한 서브시스템의 내부 구현을 알 필요 없이 간단한 인터페이스를 통해 서브시스템을 사용할 수 있게 한다.
“패턴은 복잡한 내면을 단순한 외면으로 연결하여, 심오한 이해 없이도 쉽게 다가설 수 있는 길을 연다.”
퍼사드(Facade) 패턴을 사용하면 좋은 경우는 다음과 같습니다:
- 복잡한 서브시스템을 단순화하고 싶을 때: * 서브시스템이 매우 복잡하고, 이를 사용하는 클라이언트 코드가 단순하고 명확해지도록 하고 싶은 경우. 퍼사드 패턴을 통해 클라이언트가 서브시스템의 복잡성을 알 필요 없이 사용
- 서브시스템과 클라이언트 간의 결합도를 줄이고 싶을 때: * 클라이언트가 서브시스템의 세부 구현에 의존하지 않도록 하여, 서브시스템의 변경이 클라이언트에 영향을 미치지 않게 하고 싶은 경우. 퍼사드 패턴을 통해 서브시스템의 변경이 클라이언트 코드에 미치는 영향을 최소화
- 레거시 코드를 감싸고 싶을 때: * 레거시 시스템을 현대화하거나, 기존의 복잡한 인터페이스를 단순화하여 새로운 시스템에서 쉽게 사용할 수 있도록 하고 싶은 경우. 퍼사드 패턴을 통해 레거시 시스템을 감싸서 단순한 인터페이스를 제공
- 서로 다른 여러 서브시스템을 통합하고 싶을 때: * 여러 서브시스템을 하나의 단일 인터페이스로 통합하여 일관된 방식으로 접근하고 사용할 수 있도록 하고 싶은 경우. 퍼사드 패턴을 통해 여러 서브시스템의 기능을 하나의 단순한 인터페이스로 제공
- 테스트 및 유지보수성을 향상시키고 싶을 때: * 서브시스템의 복잡한 내부 구조를 감추어 클라이언트 코드의 테스트 및 유지보수성을 높이고 싶은 경우. 퍼사드 패턴을 통해 단순한 인터페이스를 제공함으로써 테스트와 유지보수가 수월
장점
- 복잡성 감소: * 퍼사드 패턴은 복잡한 서브시스템을 단순한 인터페이스로 감싸기 때문에, 클라이언트는 서브시스템의 내부 구현을 알 필요 없이 단순하게 사용할 수 있음
- 결합도 감소: * 클라이언트와 서브시스템 간의 결합도를 줄여주고 클라이언트는 퍼사드를 통해서만 서브시스템에 접근하므로, 서브시스템의 변경이 클라이언트에 직접적인 영향을 미치지 않음
- 유지보수성 향상: * 퍼사드를 사용하면 클라이언트 코드의 유지보수성이 향상되고 클라이언트는 복잡한 서브시스템의 여러 부분을 알 필요 없이 퍼사드 인터페이스만 사용하면 되므로 코드의 가독성이 높아지고 유지보수가 용이해짐
- 재사용성 증가: * 퍼사드 패턴은 코드 재사용성을 증가시킵니다. 여러 클라이언트가 동일한 퍼사드 인터페이스를 사용할 수 있으므로, 코드의 중복을 줄이고 재사용성을 높일 수 있음
- 인터페이스 단순화: * 복잡한 서브시스템의 인터페이스를 단순화하여 클라이언트가 더 쉽게 사용할 수 있음
단점
- 추가 계층 도입: * 퍼사드 패턴은 추가적인 계층을 도입하기 때문에 퍼사드 클래스 자체가 복잡해질 수 있고 이는 퍼사드 클래스를 유지보수하는 데 어려움을 초래할 수 있음
- 서브시스템 기능 노출의 한계: * 퍼사드 패턴은 서브시스템의 모든 기능을 노출하기 어려우며 퍼사드가 제공하는 인터페이스를 통해 서브시스템의 특정 기능만 사용할 수 있으며, 모든 기능을 지원하려면 퍼사드 클래스를 계속 확장해야 함
- 성능 오버헤드: * 퍼사드 패턴을 사용하면 퍼사드 클래스에서 추가적인 메서드 호출이 발생할 수 있으므로 성능 오버헤드가 발생할 수 있고 이는 특히 성능이 중요한 시스템에서 문제가 될 수 있음
- 디자인 제약: * 퍼사드 패턴은 서브시스템의 인터페이스를 단순화하기 때문에, 서브시스템의 기능을 완벽하게 사용할 수 없게 만들 수도 있으며 이는 클라이언트가 특정 기능에 접근해야 할 때 문제를 일으킬 수 있음
퍼사드(Facade) 패턴을 사용한 그래픽 시스템 예제:
이 시스템은 이미지 로드, 처리, 렌더링뿐만 아니라, 다양한 이미지 효과 적용 및 저장 기능을 포함하고 퍼사드 패턴을 사용하여 이러한 복잡한 기능을 단순한 인터페이스로 감싸도록 한다.
// 서브시스템 클래스 1 - 이미지 로더
class ImageLoader {
public void load(String filename) {
System.out.println("Loading image: " + filename);
}
}
// 서브시스템 클래스 2 - 이미지 프로세서
class ImageProcessor {
public void process() {
System.out.println("Processing image");
}
}
// 서브시스템 클래스 3 - 이미지 렌더러
class ImageRenderer {
public void render() {
System.out.println("Rendering image");
}
}
// 서브시스템 클래스 4 - 이미지 필터
class ImageFilter {
public void applyFilter(String filter) {
System.out.println("Applying filter: " + filter);
}
}
// 서브시스템 클래스 5 - 이미지 세이버
class ImageSaver {
public void save(String filename) {
System.out.println("Saving image as: " + filename);
}
}
// 서브시스템 클래스 1 - 이미지 로더
class ImageLoader {
public void load(String filename) {
System.out.println("Loading image: " + filename);
}
}
// 서브시스템 클래스 2 - 이미지 프로세서
class ImageProcessor {
public void process() {
System.out.println("Processing image");
}
}
// 서브시스템 클래스 3 - 이미지 렌더러
class ImageRenderer {
public void render() {
System.out.println("Rendering image");
}
}
// 서브시스템 클래스 4 - 이미지 필터
class ImageFilter {
public void applyFilter(String filter) {
System.out.println("Applying filter: " + filter);
}
}
// 서브시스템 클래스 5 - 이미지 세이버
class ImageSaver {
public void save(String filename) {
System.out.println("Saving image as: " + filename);
}
}
public class FacadePatternExample {
public static void main(String[] args) {
GraphicsFacade facade = new GraphicsFacade();
// 개별 작업 수행
facade.loadImage("example.jpg");
facade.processImage();
facade.applyImageFilter("Sepia");
facade.renderImage();
facade.saveImage("processed_example.jpg");
System.out.println();
// 복합 작업 수행
facade.loadProcessRenderSave("example2.jpg", "Grayscale", "processed_example2.jpg");
}
}

코드 설명
- 서브시스템 클래스: * ImageLoader, ImageProcessor, ImageRenderer, ImageFilter, ImageSaver 클래스는 각각 이미지 로드, 처리, 렌더링, 필터 적용, 저장 기능을 담당
- 퍼사드 클래스: * GraphicsFacade 클래스는 서브시스템 클래스들을 포함하고 있으며, 클라이언트가 쉽게 사용할 수 있는 메서드를 제공합니다. 예를 들어, loadImage, processImage, renderImage, applyImageFilter, saveImage 메서드를 통해 서브시스템의 기능을 단순화 * loadProcessRenderSave 메서드는 여러 작업을 결합하여 클라이언트가 한 번의 호출로 일련의 작업을 수행할 수 있도록 함
- 클라이언트 코드: * FacadePatternExample 클래스의 main 메서드는 GraphicsFacade 객체를 생성하고, 개별 작업과 복합 작업을 수행 클라이언트는 퍼사드 인터페이스를 통해 복잡한 그래픽 시스템을 간단하게 사용할 수 있음
관련 패턴
- 어댑터(Adapter) 패턴 * 퍼사드 패턴과 어댑터 패턴 모두 인터페이스를 단순화하거나 변환하여 클라이언트가 쉽게 사용할 수 있도록 하고 퍼사드는 여러 서브시스템을 단순한 인터페이스로 감싸고, 어댑터는 하나의 클래스의 인터페이스를 변환
- 컴포지트(Composite) 패턴 * 퍼사드 패턴과 컴포지트 패턴 모두 복잡한 구조를 단순하게 만들고, 클라이언트가 쉽게 사용할 수 있도록 하며 퍼사드는 서브시스템의 복잡성을 감추고, 컴포지트는 객체 구조의 복잡성을 감춤
- 프록시(Proxy) 패턴 * 퍼사드 패턴과 프록시 패턴 모두 다른 객체에 대한 접근을 단순화하거나 제어하는 역할을 하며 퍼사드는 복잡한 서브시스템에 대한 단순한 인터페이스를 제공하고, 프록시는 접근 제어와 관련된 기능을 추가함
- 디코레이터(Decorator) 패턴 * 퍼사드 패턴과 디코레이터 패턴 모두 객체의 인터페이스를 단순화하거나 확장하여 클라이언트가 쉽게 사용할 수 있도록 하고 퍼사드는 단순화를, 디코레이터는 기능 확장을 주로 다룸
- 브리지(Bridge) 패턴 * 퍼사드 패턴과 브리지 패턴 모두 복잡성을 관리하는 데 도움을 주며 퍼사드는 단순한 인터페이스를 제공하여 복잡성을 감추고, 브리지 패턴은 추상화와 구현을 분리하여 복잡성을 줄임
- 싱글톤(Singleton) 패턴 * 퍼사드 패턴과 싱글톤 패턴은 함께 사용되어 퍼사드 객체가 전역적으로 하나만 존재하도록 할 수 있으며 이를 통해 클라이언트는 퍼사드 인터페이스를 언제나 동일한 방식으로 사용할 수 있음