쓸 수 있는 객체가 있는데 인터페이스가 맞지 않을 때, 중간에서 호출을 받아 실제 객체가 알아듣는 형태로 바꿔 주는 패턴. 전원 플러그 변환기와 같다.
interface PaymentGateway { pay(orderId: string, amount: number): Promise<void> }
class SomePaySdkAdapter implements PaymentGateway {
constructor(private sdk: SomePaySdk) {}
async pay(orderId: string, amount: number) {
await this.sdk.requestPayment({ merchantUid: orderId, price: amount })
}
}- 결제·지도·메시징처럼 업체마다 API가 다른 외부 SDK를 내부 인터페이스 하나로 맞출 때 자주 쓴다. 업체를 바꿔도 어댑터만 갈아 끼우면 된다
- 내부 코드가 외부 모델에 오염되지 않게 막는 경계 역할을 한다. 바깥 API 응답을 내부 타입으로 바꾸는 계층도 같은 생각이다(스프링에서 외부 API 호출, 바운디드 컨텍스트)
- 테스트에서 외부 서비스를 가짜로 바꾸기 쉬워진다(의존성 역전 원칙)
- 어댑터가 단순 변환을 넘어 업무 규칙을 품기 시작하면 책임이 흐려진다. 변환만 한다
인터페이스를 바꾸는 것이 어댑터, 그대로 두고 기능을 더하는 것이 데코레이터 패턴, 여러 개를 하나의 단순한 창구로 묶는 것이 퍼사드 패턴이다. 구조 패턴 전체는 구조 패턴.