개요
Facade Pattern(퍼사드 패턴)은 Gang of Four가 제시한 23개의 디자인 패턴 중 하나로, 구조적(Structural) 패턴에 속한다. 이 패턴은 복잡한 서브시스템에 대한 단순화된 인터페이스를 제공하는 것을 목적으로 한다. 퍼사드(Facade)라는 용어는 건축에서 건물의 정면을 의미하는데, 마치 건물의 복잡한 내부 구조를 감추고 깔끔한 외관만을 보여주는 것처럼, 이 패턴도 복잡한 내부 시스템의 세부사항을 숨기고 클라이언트에게 간단한 인터페이스만을 노출한다.
설명
Facade Pattern은 여러 개의 복잡하고 상호 연관된 클래스들로 구성된 서브시스템을 사용할 때, 이들을 직접 다루는 대신 하나의 통합된 인터페이스를 통해 접근할 수 있도록 하는 패턴이다. 클라이언트는 복잡한 서브시스템의 내부 구조나 상호작용을 알 필요 없이, Facade 클래스가 제공하는 단순한 메서드들을 통해 원하는 기능을 수행할 수 있다.
이 패턴의 핵심 아이디어는 "복잡성의 캡슐화"이다. 서브시스템이 진화하고 복잡해져도 클라이언트 코드는 Facade 인터페이스에만 의존하므로 변경의 영향을 최소화할 수 있다. 또한 서브시스템의 올바른 사용법을 Facade에 캡슐화함으로써, 클라이언트가 서브시스템을 잘못 사용할 가능성을 줄인다.
Facade Pattern의 구조는 다음과 같다:
- Facade: 클라이언트가 사용하는 단순화된 인터페이스를 제공하며, 내부적으로 여러 서브시스템 컴포넌트들을 조율한다
- Subsystem Classes: 실제 작업을 수행하는 복잡한 클래스들의 집합이다
- Client: Facade를 통해 서브시스템의 기능을 사용하는 클라이언트 코드이다
특성
Facade Pattern의 주요 특성들은 다음과 같다:
- 단순화된 인터페이스: 복잡한 서브시스템에 대한 간단하고 직관적인 인터페이스를 제공한다. 클라이언트는 복잡한 API 호출 순서나 의존성을 신경 쓸 필요가 없다.
- 느슨한 결합(Loose Coupling): 클라이언트와 서브시스템 간의 결합도를 낮춘다. 클라이언트는 Facade에만 의존하므로, 서브시스템의 변경이 클라이언트에 미치는 영향을 최소화한다.
- 복잡성 은닉: 서브시스템의 복잡한 내부 구조와 상호작용을 클라이언트로부터 숨긴다. 이는 코드의 가독성과 유지보수성을 향상시킨다.
- 계층화: 서브시스템에 계층적 구조를 도입하여 의존성을 정리한다. 각 서브시스템은 자신만의 Facade를 가질 수 있어 더 큰 시스템에서도 계층적으로 구성할 수 있다.
- 유연성 제공: 클라이언트는 필요에 따라 Facade를 통한 단순한 접근과 서브시스템에 대한 직접 접근을 선택할 수 있다.
- 재사용성 향상: 공통적으로 사용되는 서브시스템 조합을 Facade로 래핑함으로써 코드의 재사용성을 높인다.
예시
다음은 홈 시어터 시스템을 예로 든 Facade Pattern의 구현이다:
// 서브시스템 클래스들
class Amplifier {
public void on() { System.out.println("앰프 켜기"); }
public void off() { System.out.println("앰프 끄기"); }
public void setVolume(int volume) {
System.out.println("음량을 " + volume + "으로 설정");
}
}
class DVDPlayer {
public void on() { System.out.println("DVD 플레이어 켜기"); }
public void off() { System.out.println("DVD 플레이어 끄기"); }
public void play(String movie) {
System.out.println(movie + " 재생");
}
public void stop() { System.out.println("DVD 정지"); }
}
class Projector {
public void on() { System.out.println("프로젝터 켜기"); }
public void off() { System.out.println("프로젝터 끄기"); }
public void wideScreenMode() {
System.out.println("와이드 스크린 모드로 설정");
}
}
class TheaterLights {
public void dim(int level) {
System.out.println("조명을 " + level + "%로 어둡게 설정");
}
public void on() { System.out.println("조명 켜기"); }
}
class Screen {
public void up() { System.out.println("스크린 올리기"); }
public void down() { System.out.println("스크린 내리기"); }
}
// Facade 클래스
class HomeTheaterFacade {
private Amplifier amp;
private DVDPlayer dvd;
private Projector projector;
private TheaterLights lights;
private Screen screen;
public HomeTheaterFacade(Amplifier amp, DVDPlayer dvd,
Projector projector, TheaterLights lights,
Screen screen) {
this.amp = amp;
this.dvd = dvd;
this.projector = projector;
this.lights = lights;
this.screen = screen;
}
public void watchMovie(String movie) {
System.out.println("영화 감상 준비 중...");
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie() {
System.out.println("홈 시어터 시스템 종료 중...");
dvd.stop();
dvd.off();
amp.off();
projector.off();
screen.up();
lights.on();
}
}
// 클라이언트 코드
public class HomeTheaterTest {
public static void main(String[] args) {
// 서브시스템 컴포넌트들 생성
Amplifier amp = new Amplifier();
DVDPlayer dvd = new DVDPlayer();
Projector projector = new Projector();
TheaterLights lights = new TheaterLights();
Screen screen = new Screen();
// Facade 생성
HomeTheaterFacade homeTheater = new HomeTheaterFacade(
amp, dvd, projector, lights, screen);
// 간단한 메서드 호출로 복잡한 작업 수행
homeTheater.watchMovie("아바타");
System.out.println();
homeTheater.endMovie();
}
}
또 다른 실용적인 예시로는 데이터베이스 접근 Facade가 있다:
// 복잡한 데이터베이스 관련 클래스들
class DatabaseConnection {
public void connect() { System.out.println("데이터베이스 연결"); }
public void disconnect() { System.out.println("데이터베이스 연결 해제"); }
}
class QueryBuilder {
public String buildSelectQuery(String table, String[] fields) {
return "SELECT " + String.join(",", fields) + " FROM " + table;
}
}
class ResultProcessor {
public void processResults(String query) {
System.out.println("쿼리 실행 및 결과 처리: " + query);
}
}
class TransactionManager {
public void beginTransaction() { System.out.println("트랜잭션 시작"); }
public void commit() { System.out.println("트랜잭션 커밋"); }
public void rollback() { System.out.println("트랜잭션 롤백"); }
}
// Database Facade
class DatabaseFacade {
private DatabaseConnection connection;
private QueryBuilder queryBuilder;
private ResultProcessor resultProcessor;
private TransactionManager transactionManager;
public DatabaseFacade() {
this.connection = new DatabaseConnection();
this.queryBuilder = new QueryBuilder();
this.resultProcessor = new ResultProcessor();
this.transactionManager = new TransactionManager();
}
public void findUser(String userId) {
connection.connect();
String query = queryBuilder.buildSelectQuery("users",
new String[]{"id", "name", "email"});
resultProcessor.processResults(query + " WHERE id = " + userId);
connection.disconnect();
}
public void updateUserTransaction(String userId, String newData) {
connection.connect();
transactionManager.beginTransaction();
try {
System.out.println("사용자 " + userId + " 데이터 업데이트: " + newData);
transactionManager.commit();
} catch (Exception e) {
transactionManager.rollback();
}
connection.disconnect();
}
}
결론
Facade Pattern은 복잡한 서브시스템을 단순화된 인터페이스로 래핑 하여 사용자 친화적인 API를 제공하는 강력한 디자인 패턴이다. 이 패턴의 핵심 가치는 복잡성을 숨기고 사용 편의성을 높이는 데 있다.
현대 소프트웨어 개발에서 Facade Pattern은 매우 널리 사용되고 있다. 특히 마이크로서비스 아키텍처에서는 API Gateway가 Facade 역할을 수행하여 여러 서비스들에 대한 통합된 인터페이스를 제공한다. 또한 복잡한 라이브러리나 프레임워크를 사용할 때도 Facade를 통해 필요한 기능만을 간단하게 노출시키는 경우가 많다.
다만 Facade Pattern 사용 시 주의해야 할 점도 있다. Facade가 너무 많은 책임을 지게 되면 하나의 거대한 클래스가 되어 유지보수가 어려워질 수 있다. 또한 성능이 중요한 상황에서는 Facade가 추가하는 간접 계층이 오버헤드가 될 수 있으므로 적절한 균형을 찾는 것이 중요하다.
결론적으로 Facade Pattern은 복잡한 시스템을 다룰 때 코드의 가독성과 유지보수성을 크게 향상시킬 수 있는 유용한 패턴이다. 특히 레거시 시스템을 현대화하거나 복잡한 외부 API를 래핑 할 때 그 진가를 발휘한다.
참고문헌
- Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional.
- Freeman, E., Robson, E., Bates, B., & Sierra, K. (2004). Head First Design Patterns. O'Reilly Media.
- Bloch, J. (2017). Effective Java (3rd Edition). Addison-Wesley Professional.
- Martin, R. C. (2017). Clean Architecture: A Craftsman's Guide to Software Structure and Design. Prentice Hall.
- Refactoring Guru. Facade Pattern. https://refactoring.guru/design-patterns/facade
- Oracle. Java Documentation - Design Patterns. https://docs.oracle.com/javase/tutorial/
'Research > Software Engineering' 카테고리의 다른 글
데이터 WBS(Work Breakdown Structure): 데이터 프로젝트 성공을 위한 체계적 접근법 (2) | 2025.05.28 |
---|---|
소프트웨어 개발 분야의 Use Case: 사용자 중심 요구사항 분석의 핵심 도구 (0) | 2025.05.27 |
소프트웨어 개발 분야의 도메인 이해와 적용 (3) | 2025.05.15 |
SEED: 국내 표준 암호 알고리즘 (2) | 2025.03.24 |
ARIA: 국내 표준 암호 알고리즘 (2) | 2025.03.23 |