📝 Facade Pattern(퍼사드 패턴)
- (사전적 의미) 건축물의 정면
- 복잡한 서브 클래스의 기능을 정리해서 상위 수준의 인터페이스를 제공하는 디자인 패턴
| 역할 | 설명 |
|---|---|
| Facade | 서브시스템 기능을 편리하게 사용할 수 있도록 복잡한 로직을 정리해 상위 수준의 인터페이스를 구성 |
| Additional Facade | 퍼사드 내부 코드의 양 증가 등으로 분리가 필요할 경우 도메인 별로 추가적인 퍼사드 객체를 생성해 사용 |
| SubSystem | 라이브러리 또는 클래스 |
| Client | 서브시스템에 직접 접근하지 않고 퍼사드에 접근해서 사용 |
⌨️ 코드 구현
문제 상황
하나의 서비스에서 외부 API 호출과 데이터 저장이 하나의 트랜잭션으로 묶여 있어 트랜잭션 시간 제한(3초)을 초과하는 상황
- 외부 API 호출 포트로 외부 시스템에 데이터 요청 (3.5초 소요)
- 저장 포트로 데이터베이스에 데이터 저장(예시에서는 로그로 대체)
@Slf4j
@Service
@RequiredArgsConstructor
public class DataFacade implements DataUseCase {
private static final long TRANSACTION_TIMEOUT_SECONDS = 3L;
private final ExternalApiPort externalApiPort;
private final SavePort savePort;
@Override
public Data processData(String content) {
log.info("트랜잭션 시작 - 내용: {}", content);
/*
(예제 코드) 외부 API 호출과 저장 로직이 하나의 트랜잭션으로 연결되어있다는 것을 표현
*/
try {
return CompletableFuture
.supplyAsync(() -> {
// callExternalApi 호출 시 3.5초 시간 소요
String id = externalApiPort.callExternalApi(content);
Data result = new Data(id, content);
savePort.save(result);
return result;
})
.orTimeout(TRANSACTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.join();
} catch (Exception e) {
log.error("트랜잭션 롤백", e);
if (e.getCause() instanceof TimeoutException) {
throw new RuntimeException("트랜잭션 시간 제한 초과: " + TRANSACTION_TIMEOUT_SECONDS + "초", e);
}
throw new RuntimeException("데이터 처리 실패", e);
}
}
}
제약사항
- 트랜잭션 시간 변경 금지
- 어댑터 수정 금지
전체 흐름

외부 API 호출을 트랜잭션 밖으로 분리하고, Facade가 전체 흐름을 관리하는 형태로 변경
Facade(DataFacade)
@Slf4j
@Service
@RequiredArgsConstructor
public class DataFacade implements DataUseCase {
private static final long TRANSACTION_TIMEOUT_SECONDS = 3L;
private final DataProcessService dataProcessService;
private final DataSaveService dataSaveService;
@Override
public Data processData(String content) {
log.info("트랜잭션 시작 - 내용: {}", content);
try {
Data result = dataProcessService.processData(content);
dataSaveService.save(result);
return result;
} catch (Exception e) {
log.error("트랜잭션 롤백", e);
if (e.getCause() instanceof TimeoutException) {
throw new RuntimeException("트랜잭션 시간 제한 초과: " + TRANSACTION_TIMEOUT_SECONDS + "초", e);
}
throw new RuntimeException("데이터 처리 실패", e);
}
}
}
SubSystem(DataProcessService, DataSaveService)
@Slf4j
@Service
@RequiredArgsConstructor
public class DataProcessService {
private final ExternalApiPort externalApiPort;
String getContentId(String content) {
return externalApiPort.callExternalApi(content);
}
public Data processData(String content) {
String id = this.getContentId(content);
return new Data(id, content);
}
}
@Slf4j
@Service
@RequiredArgsConstructor
public class DataSaveService {
private final SavePort savePort;
// 실제 DB를 사용하는 경우 이 메서드에 @Transactional 적용
public void save(Data data) {
savePort.save(data);
}
}
🔗 참고 자료
💠 퍼사드(Facade) 패턴 - 완벽 마스터하기
Facade Pattern 퍼사드 패턴(Facade Pattern)은 사용하기 복잡한 클래스 라이브러리에 대해 사용하기 편하게 간편한 인터페이스(API)를 구성하기 위한 구조 패턴 이다. 예를들어 라이브러리의 각 클래스
inpa.tistory.com
[Design Pattern] Facade Pattern (퍼사드 패턴)
퍼사드 패턴(Facade Pattern)은 구조 패턴(Structural Pattern)의 한 종류로써, 복잡한 서브 클래스들의 공통적인 기능을 정의하는 상위 수준의 인터페이스를 제공하는 패턴이다.퍼사드 객체(Facade Object)는
velog.io
'𝑺𝒕𝒖𝒅𝒚 > 디자인 패턴' 카테고리의 다른 글
| [JAVA/Spring Boot] getter interface를 활용해 OCP를 준수한 SapMapper 구현하기 (0) | 2026.04.23 |
|---|---|
| [JAVA/Spring Boot] 위임(Delegate) 패턴 + 전략(Strategy) 패턴 조합으로 조건문이 필요없는 정수 사칙연산 계산기 만들기 (0) | 2026.03.27 |