1. 파사드 패턴이란?
- 파사드(Facade) 패턴은 복잡한 서브시스템에 대한 간단한 인터페이스를 제공하는 구조적 디자인 패턴입니다.
- 이 패턴은 라이브러리, 프레임워크 또는 복잡한 클래스 집합에 대한 단순화된 인터페이스를 제공합니다.
- 파사드는 클라이언트가 복잡한 서브시스템의 내부 동작을 이해하지 않고도 필요한 기능을 쉽게 사용할 수 있게 합니다.
1.1 파사드 패턴의 목적
- 복잡한 시스템의 사용 난이도를 낮춤
- 서브시스템에 대한 의존성 감소
- 클라이언트 코드와 서브시스템 간의 결합도 감소
- 코드의 가독성과 유지보수성 향상
2. 문제 상황
- 복 잡한 라이브러리나 프레임워크를 사용할 때 많은 객체를 초기화하고, 의존성을 추적하며, 올바른 순서로 메서드를 실행해야 합니다.
- 이로 인해 비즈니스 로직이 서드파티 클래스의 구현 세부사항과 강하게 결합되어 코드 이해와 유지보수가 어려워집니다.
2.1 실생활 예시
- 전화로 상품을 주문할 때 상담원은 주문 시스템, 결제 게이트웨이, 배송 서비스 등 가게의 모든 서비스와 부서에 대한 파사드 역할을 합니다.
- 상담원은 복잡한 주문 시스템의, 단순한 음성 인터페이스를 제공합니다.
팁
파사드 패턴은 마치 복잡한 기계의 간단한 제어판과 같습니다. 내부 작동 방식은 복잡하지만, 사용자(클라이언트)는 몇 개의 버튼만 눌러 원하는 기능을 사용할 수 있습니다.
3. 파사드 패턴의 구조
3.1 주요 구성 요소

- 파사드(Facade): 서브시스템의 기능에 대한 편리한 접근을 제공하는 클래스입니다. 클라이언트 요청을 어디로 전달할지 알고 있으며 모든 구성 요소를 작동시키는 방법을 알고 있습니다.
- 추가 파사드(Additional Facade): 단일 파사드에 관련 없는 기능들로 오염되는 것을 방지하기 위해 생성할 수 있는 클래스입니다.
- 복잡한 서브시스템(Complex Subsystem): 수십 개의 다양한 객체로 구성됩니다. 서브시스템 클래스들은 파사드의 존재를 알지 못하며, 시스템 내에서 서로 직접 작동합니다.
- 클라이언트(Client): 서브시스템 객체를 직접 호출하는 대신 파사드를 사용합니다.
3.2 구조 다이어그램
+----------------+ +----------------+
| Client |----->| Facade |
+----------------+ +----------------+
|
|
v
+--------------+
| |
+----->| Subsystem A |
| | |
| +--------------+
|
| +--------------+
| | |
+----->| Subsystem B |
| | |
| +--------------+
|
| +--------------+
| | |
+----->| Subsystem C |
| |
+--------------+
4. 파사드 패턴 구현 방법
4.1 구현 단계
- 기존 서브시스템보다 간단한 인터페이스를 제공할 수 있는지 확인합니다.
- 새로운 파사드 클래스에서 이 인터페이스를 선언하고 구현합니다.
- 파사드는 클라이언트 코드의 호출을 서브시스템의 적절한 객체로 리디렉션해야 합니다.
- 모든 클라이언트 코드가 오직 파사드를 통해서만 서브시스템과 통신하도록 합니다.
- 파사드가 너무 커진다면, 그 동작의 일부를 새로운 파사드 클래스로 추출하는 것을 고려합니다.
4.2 코드 예제
다음은 복잡한 비디오 변환 프레임워크에 대한 파사드 패턴 구현 예시입니다.
복잡한 서브시스템 클래스
// 복잡한 서드파티 비디오 변환 프레임워크의 일부 클래스입니다.
// 우리는 이 코드를 제어할 수 없으므로 단순화할 수 없습니다.
class VideoFile {
private String name;
public VideoFile(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class OggCompressionCodec {
// 구현 생략
}
class MPEG4CompressionCodec {
// 구현 생략
}
class CodecFactory {
public static Codec extract(VideoFile file) {
// 코덱 추출 로직
return new OggCompressionCodec();
}
}
class BitrateReader {
public static byte[] read(VideoFile file, Codec codec) {
// 파일 읽기 로직
return new byte[0];
}
public static byte[] convert(byte[] buffer, Codec codec) {
// 변환 로직
return new byte[0];
}
}
class AudioMixer {
public byte[] fix(byte[] audioData) {
// 오디오 수정 로직
return new byte[0];
}
}
interface Codec {
// 코덱 인터페이스
}
파사드 클래스 구현
class VideoConverter {
public File convert(String filename, String format) {
VideoFile file = new VideoFile(filename);
Codec sourceCodec = CodecFactory.extract(file);
Codec destinationCodec;
if (format.equals("mp4")) {
destinationCodec = new MPEG4CompressionCodec();
} else {
destinationCodec = new OggCompressionCodec();
}
byte[] buffer = BitrateReader.read(file, sourceCodec);
byte[] result = BitrateReader.convert(buffer, destinationCodec);
result = (new AudioMixer()).fix(result);
return new File(result);
}
}
- 프레임워크의 복잡성을 간단한 인터페이스 뒤에 숨기는 파사드 클래스를 생성합니다.
VideoConverter클래스는 비디오 파일을 변환하는 단순한 메서드convert를 제공합니다.- 이 메서 드는 내부적으로 복잡한 서브시스템의 여러 클래스를 사용하여 비디오 파일을 변환합니다.
- 클라이언트는
VideoConverter클래스의convert메서드만 호출하면 됩니다.
클라이언트 코드
class Application {
public static void main(String[] args) {
VideoConverter converter = new VideoConverter();
File mp4 = converter.convert("funny-cats-video.ogg", "mp4");
mp4.save();
}
}
- 클라이언트는
VideoConverter클래스의convert메서드를 호출하여 비디오 파일을 변환합니다. - 클라이언트는 파사드의
convert메서드만 호출하면, 내부적으로 복잡한 프레임워크의 여러 클래스와 메서드가 사용됩니다.
정보
파사드 패턴은 단순히 복잡한 서브시스템을 감추는 것보다, 클라이언트의 실제 요구에 맞게 필요한 기능만을 제공하는 것이 중요합니다. 모든 기능을 제공하는 것이 아니라, 클라이언트가 정말로 관심 있는 기능만 포함하는 것이 좋습니다.
5. 파사드 패턴 적용 시기
- 복잡한 서브시스템에 대한 제한적이지만 간단한 인터페이스가 필요할 때
- 서브시스템을 레이어로 구조화하고 싶을 때
- 서브시스템의 복잡성이 시간이 지남에 따라 증가하는 경우