최근 우테코 프리코스에서 코드 리뷰를 진행하면서 Facade 패턴이라는 개념을 다시 접하게 되었다. 예전에 정보처리기사 공부를 할 때 한 번쯤 들어봤던 개념이지만, 그 당시에는 단순히 용어 정도로만 알고 넘어갔다.
그런데 이번에 다시 보니 뭔가 Service 계층과 비슷한 느낌이 들어 정확히 어떤 개념인지 다시 공부해보고 싶다는 생각이 들었다.
Facade 패턴이란?
Facade는 '건물의 정면'이라는 의미를 가진다. 건물의 내부 구조가 아무리 복잡해도, 외부에서는 정면만 보듯이 복잡한 시스템의 내부를 단순한 인터페이스로 감싸는 구조적 디자인 패턴이다.
즉, 복잡한 하위 시스템을 하나의 창구로 단순하게 노출하는 것을 목표로 한다.
- 복잡한 로직이나 다수의 클래스가 얽혀 있을 때, 그 위헤 하나의 진입점(Facade 클래스)을 두어 단순하게 사용할 수 있도록 만든다.
- 사용자는 내부 구현을 몰라도 되며, Facade를 통해서만 기능에 접근한다.
여러 출처에서 본 정의
apigee의 API Facade Pattern에서는 API Facade Design Pattern을 아래과 같이 설명하고 있다.
Facade 디자인 패턴은 백엔드 및 내부 시스템이 애플리케이션 개발자들에게 직접 노출되기에 너무 복잡할 때 생기는 문제를 해결하기 위한 솔루션이다.
The API Facade Design Pattern is a solution to a design problem that arises for API designers when back-end and internal systems of record are too complex to expose directly to application developers
Refactoring.Gurue에서는 퍼사드 패턴을 아래와 같이 설명하고 있다.
Facade는 구조적 디자인 패턴으로, 복잡한 클래스(예: 라이브러리나 프레임워크 등)에 대해 단순화된 인터페이스를 제공하는 패턴이다.
Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes.
위키백과에서는 퍼사드 패턴을 아래과 같이 설명하고 있다.
퍼사드는 클래스 라이브러리 같은 어떤 소프트웨어의 다른 커다란 코드 부분에 대한 간략화된 인터페이스를 제공하는 객체이다
요약하면 "복잡한 시스템을 감추고, 단순한 인터페이스를 제공한다"라는 점에서 모두 공통된 설명을 하고 있다.
퍼사드 패턴 구조

- Facade: 서브 시스템 기능을 편리하게 사용할 수 있도록 하기 위해 여러 시스템과 상호 작용하는 복잡한 로직을 재정리해서 높은 레벨인터페이스를 구성한다. Facade 역할은 서브 시스템의 많은 역할에 대해 '단순한 창구'가 된다. 클라이언트와 서브 시스템은 서로 긴밀하게 연결되지 않도록 한다.
- Additional Facade: 퍼사드 클래스는 반드시 한 개만 존재해야 한다는 규칙 같은 건 없다. 연관되지 않은 기능이 있다면 퍼사드 2세로 분리한다. 이 퍼사드 2세는 다른 퍼사드에서 사용할 수도 있고 클라이언트에서 직접 접근할 수 있다.
- SubSystem(하위 시스템): 수십 가지 라이브러리 혹은 클래스들
- Client: 서브 시스템에 직접 접근하는 대신 Facade를 사용한다.
퍼사드는 전략 패턴이나 팩토리 패턴 같은 다른 디자인 패턴과 다르게 특정 형태의 클래스 구조를 강제하지 않는다.
단순히 복잡한 로직을 한 곳으로 모아 단순하게 제공하는 것이 핵심이다.

예시 코드
// SubSystem A
public class VideoFile {
public void load(String fileName) { ... }
}
// SubSystem B
public class AudioMixer {
public void adjustAudio() { ... }
}
// Facade
public class VideoConverterFacade {
private final VideoFile videoFile = new VideoFile();
private final AudioMixer audioMixer = new AudioMixer();
public void convert(String fileName) {
videoFile.load(fileName);
audioMixer.adjustAudio();
System.out.println("비디오 변환 완료");
}
}
// Client
public class Client {
public static void main(String[] args) {
VideoConverterFacade converter = new VideoConverterFacade();
converter.convert("movie.mp4");
}
}
→ 내부적으로 여러 클래스가 협력하지만, 사용자는 `convert()` 하나만 호출하면 된다.
Facade 패턴 특징
💡 사용하는 시점
- 시스템이 너무 복잡해 외부에서 사용하기 어려울 때
- 여러 모듈/클래스 간 결합도가 높아 유지보수가 어려울 때
- 외부에서 단순하고 일관된 인터페이스를 제공하고 싶을 때
✅ 장점
- 복잡한 내부 구조를 숨기고 단순한 인터페이스 제공
- 하위 시스템의 의존 관계를 줄이고 의존성을 한 곳으로 모을 수 있다.
- 복잡한 코드 감춤 → 클라이언트가 시스템의 콛를 모르더라도 Facade 클래스만 이해하고 사용가능하다.
⚠️ 단점
- Facade가 비대해지면 앱의 모든 클래스에 결합된 "God 객체"가 될 수 있음
- 하위 시스템 의존성을 완전히 제거하지 못함
- 코드 양과 관리 포인트가 늘어 유지보수 비용이 증가
결국, 시스템 복잡도 대비 얻는 이점을 따져 균형 있게 적용해야 하는 패턴이다.
Spring 구조에서의 Facade 패턴
Spring에서 Facade를 Service 위의 계층으로 두는 경우가 많다. 여러 Service를 조합하여 하나의 유스 케이스 단위로 실행하고, 트랜잭션을 Facade 단에서 관리하도록 설계한다.
계층별 역할 정리
Controller → Facade → Service → Repository

| 계층 | 역할 |
| Controller | 클라이언트 요청/응답 처리, 입력값 검증 |
| Facade | 여러 Service 조합, 트랜잭션 관리, DTO 변환(Converter 활용) |
| Service | 개별 엔티티의 CRUD 및 비즈니스 로직 수행, 존재 여부 검증, 형식적 validation 수행 |
| Repository | 실제 DB 접근 (데이터 조회/저장/삭제) |
예시 코드
기존 구조 (Service 간 직접 의존)
@Service
public class ProductService {
private final CouponService couponService;
public ProductService(CouponService couponService) {
this.couponService = couponService;
}
@Transactional
public void createProductWithCoupon(Product product) {
productRepository.save(product);
couponService.issueCoupon(product);
}
}
→ 단순하지만, 트랜잭션 경계가 불명확하고 순환 참조 위험이 있다.
Facade를 도입한 구조
@Service
@Transactional
public class ProductFacade {
private final ProductService productService;
private final CouponService couponService;
public ProductFacade(ProductService productService, CouponService couponService) {
this.productService = productService;
this.couponService = couponService;
}
public void createProductWithCoupon(ProductRequest request) {
Product product = productService.create(request);
couponService.issueCoupon(product);
}
}
@RestController
@RequiredArgsConstructor
public class ProductController {
private final ProductFacade productFacade;
@PostMapping("/products")
public ResponseEntity<Void> createProduct(@RequestBody ProductRequest request) {
productFacade.createProductWithCoupon(request);
return ResponseEntity.ok().build();
}
}
→ `Controller`는 `Facade`만 알고
→ `Facade`는 여러 `Service`를 조합하여 트랜잭션을 관리한다.
개인적인 메모
처음에는 간단한 예시 코드만 보고 “이건 그냥 `Service`나 `Domain`으로도 만들 수 있지 않을까?”라고 생각했다.
그런데 다른 사람들이 작성한 좀 더 구체적인 예시를 보니, `Facade`는 여러 `Service`의 협력을 조율하는 조립자 같은 역할이라는 걸 이해하게 되었다.
참고
facade API와 Shopping Service API팀에 대한 이야기
[우아한테크세미나] 190620 우아한객체지향 by 우아한형제들 개발실장 조영호님
'CS' 카테고리의 다른 글
| [CS] Observer Pattern(옵저버 패턴) (0) | 2026.01.22 |
|---|---|
| [CS] Strategy Pattern(전략 패턴) (0) | 2026.01.07 |
| [CS] Factory Pattern(팩토리 패턴) (0) | 2026.01.03 |
| [CS] Singleton Pattern(싱글톤 패턴) (0) | 2025.12.17 |
| 객체 지향 프로그래밍(Object-Oriented Programming, OOP) (0) | 2025.10.17 |