트렌드브리프
퍼사드 패턴이란? 개념과 예제, 어댑터·프록시 차이

퍼사드 패턴이란? 개념과 예제, 어댑터·프록시 차이

· 게시 · 약 6분 분량

퍼사드 패턴은 복잡한 서브시스템을 하나의 단순한 창구로 감싸 클라이언트가 내부 순서와 의존 관계를 몰라도 쓰게 하는 GoF 구조 패턴이다. 개념과 사용 시점, 어댑터·프록시 패턴과의 차이를 코드 예제와 함께 정리했다.

목차
  1. 퍼사드 패턴이란 무엇인가
  2. 언제 퍼사드 패턴이 필요한가
  3. 코드로 보는 최소 퍼사드
  4. 실무에서 만나는 파사드: 로깅 라이브러리
  5. 어댑터·프록시 패턴과의 차이
  6. 퍼사드를 쓸 때 조심할 것

퍼사드 패턴(facade pattern)은 여러 갈래로 나뉜 복잡한 기능을 하나의 단순한 창구로 감싸는 설계 방식이다. 클라이언트는 내부 부품을 일일이 다루는 대신 창구 하나만 호출하고, 부품끼리의 호출 순서나 의존 관계는 창구 뒤로 숨는다. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 네 사람이 1994년에 펴낸 『Design Patterns』(흔히 'GoF 책'이라 부른다)가 정리한 23가지 패턴 중 하나이며, 구조(structural) 패턴으로 분류된다.

이 글은 객체지향 소프트웨어 설계 관점에서 퍼사드 패턴이 무엇이고 언제 쓰는지, 어댑터·프록시 패턴과 어떻게 다른지를 다룬다. 특정 언어나 프레임워크에 매이지 않은 개념 설명이라, 예제는 이해를 돕는 최소 코드로만 넣었다.

퍼사드 패턴이란 무엇인가

복잡한 서브시스템 앞에 '단일 진입점' 역할을 하는 객체를 하나 두는 것이다. 디자인 패턴 참고 사이트 Refactoring.Guru는 퍼사드를 라이브러리·프레임워크처럼 부품이 많은 묶음에 단순한 인터페이스를 제공하는 구조 패턴으로 설명한다. GoF 책은 이를 더 딱딱하게 규정한다. 서브시스템의 여러 인터페이스에 대한 통합된 인터페이스를 제공하고, 서브시스템을 더 쉽게 쓰도록 상위 수준 인터페이스를 정의한다는 것이다.

비유하면 식당 홀 서버다. 손님은 주방·창고·계산대가 각각 어떻게 돌아가는지 몰라도 서버에게 주문만 넘기면 된다. 서버가 주방에 조리를 시키고, 재고를 확인하고, 계산서를 붙이는 순서를 대신 처리한다. 퍼사드 객체가 이 서버 역할을 맡아 클라이언트(서비스를 호출하는 쪽)와 내부 부품 사이를 중개한다.

언제 퍼사드 패턴이 필요한가

서브시스템이 복잡한데 클라이언트가 그중 일부 기능만 반복해서 쓸 때다. 부품을 직접 다루면 클라이언트 코드가 내부 구현에 달라붙어(결합도가 높아져) 나중에 손대기 어려워진다. 다음 상황이면 퍼사드를 고려할 만하다.

핵심 이득은 결합도를 낮추는 것이다. 클라이언트는 창구의 메서드 이름만 알면 되고, 내부에서 어떤 클래스가 어떤 순서로 불리는지는 몰라도 된다. Refactoring.Guru도 퍼사드가 애플리케이션 전체의 복잡도를 낮추고 원치 않는 의존성을 한곳으로 모은다는 점을 이점으로 든다.

코드로 보는 최소 퍼사드

주문 처리를 예로 들어 보자. 재고·결제·배송이라는 세 서브시스템이 있고, 주문은 늘 '재고 예약 → 결제 → 배송 예약' 순서로 돌아간다. 이 순서를 퍼사드 하나로 묶으면 클라이언트는 절차를 몰라도 된다.

// 서브시스템: 각자 자기 일만 안다
class Inventory {
 reserve(itemId) { /* 재고 확인·예약 */ }
}
class Payment {
 charge(amount) { /* 결제 승인 */ }
}
class Shipping {
 schedule(itemId) { /* 배송 예약 */ }
}

// 퍼사드: 세 서브시스템을 하나의 창구로 묶는다
class OrderFacade {
 constructor() {
 this.inventory = new Inventory();
 this.payment = new Payment();
 this.shipping = new Shipping();
 }
 placeOrder(itemId, amount) {
 this.inventory.reserve(itemId);
 this.payment.charge(amount);
 this.shipping.schedule(itemId);
 }
}

// 클라이언트: 내부 순서를 몰라도 된다
new OrderFacade().placeOrder("A-100", 39000);

클라이언트가 아는 것은 placeOrder 하나뿐이다. 결제 전에 쿠폰 검증을 끼워 넣거나 배송 업체를 바꿔도 수정은 OrderFacade 안에서 끝난다. 클라이언트 코드는 손대지 않는다. 이렇게 '바뀔 곳을 한곳으로 모으는' 것이 퍼사드의 실질적인 값어치다.

손님이 단순한 창구를 상대하고, 벽 뒤에는 기어·배관이 얽힌 복잡한 서브시스템이 있는 선화 일러스트
손님은 단순한 창구 하나만 상대하고, 그 뒤의 복잡한 서브시스템은 퍼사드가 조율한다.

실무에서 만나는 파사드: 로깅 라이브러리

낯선 개념 같지만 이미 널리 쓰는 도구 중에 퍼사드가 있다. 자바 진영의 SLF4J가 대표적이다. SLF4J 공식 사이트는 이 라이브러리를 java.util.logging, Logback, Log4j 같은 여러 로깅 프레임워크에 대한 단순한 파사드(추상화)라고 소개한다. 이름 자체가 'Simple Logging Facade for Java'다.

동작 방식이 퍼사드의 교과서다. 애플리케이션 코드는 SLF4J API 하나에만 의존해 로그를 남기고, 실제 로깅 구현체는 배포 시점에 클래스패스의 바인딩만 바꿔 교체한다. SLF4J 공식 문서에 따르면 라이브러리를 SLF4J로 만들 때 필수 의존성은 slf4j-api.jar 하나뿐이고, 클래스패스에서 적절한 바인딩을 못 찾으면 아무 동작도 하지 않는 no-op 구현으로 기본 동작한다. 로깅 구현을 통째로 갈아끼워도 애플리케이션 코드는 그대로 두는 이 유연함이 파사드로 감싼 덕이다.

여러 부품을 정해진 순서로 엮어 하나의 상위 흐름으로 부른다는 발상은 AI 에이전트의 그래프 오케스트레이션에서 노드와 엣지로 흐름을 제어하는 방식과도 결이 닿는다. 다만 오케스트레이션이 흐름의 분기와 조건에 무게를 둔다면, 퍼사드는 입구를 하나로 좁히는 데 초점이 있다.

어댑터·프록시 패턴과의 차이

셋 다 다른 객체를 감싼다는 점은 같지만 목적이 다르다. 퍼사드는 복잡한 여러 개를 단순한 하나로 묶고, 어댑터는 안 맞는 인터페이스를 맞춰 끼우며, 프록시는 같은 인터페이스를 유지한 채 접근 제어나 캐싱 같은 기능을 얹는다.

패턴목적인터페이스 관계
퍼사드복잡한 서브시스템을 단순한 창구로 묶기새로운 단순 인터페이스를 제공
어댑터호환 안 되는 인터페이스를 맞춰 연결기존 인터페이스를 다른 형태로 변환
프록시접근 제어·지연 로딩·캐싱 등을 추가원본과 같은 인터페이스를 유지

구분이 헷갈리면 '인터페이스를 어떻게 다루나'를 보면 된다. 퍼사드는 인터페이스를 새로 단순하게 만들고, 어댑터는 형태만 바꾸며, 프록시는 그대로 둔 채 대리한다.

퍼사드를 쓸 때 조심할 것

가장 흔한 함정은 퍼사드가 비대해지는 것이다. 편하다고 로직을 자꾸 붙이면 퍼사드 자체가 모든 걸 떠안는 갓 오브젝트(god object, 하나가 너무 많은 책임을 지는 객체)가 되고, 없애려던 복잡함이 창구 안으로 옮겨 갈 뿐이다. 다음을 지키면 이 함정을 피한다.

퍼사드는 새 기능을 만드는 패턴이 아니라 이미 있는 복잡함을 다루기 쉬운 크기로 줄이는 패턴이다. 이 선을 지킬 때만 창구는 짐이 아니라 지름길로 남는다.

더 많은 글 보기 RSS 구독