Back-End/Java & Spring

Adapter 패턴 : 호환되지 않는 인터페이스를 연결하는 설계 전략

봉의일상 2025. 5. 11. 22:23

1. Adapter 패턴이란?

Adapter 패턴은 서로 호환되지 않는 두 객체를 연결해주는 중간 매개체 역할을 하는 구조 패턴입니다. 즉, 기존 인터페이스를 클라이언트가 기대하는 인터페이스로 변환하여, 기존 코드의 변경 없이도 새로운 기능을 통합할 수 있게 해줍니다.

사용 목적

  • 기존 코드를 수정하지 않고 외부 시스템 또는 레거시 코드를 통합
  • 인터페이스가 맞지 않아 함께 사용하기 어려운 두 객체를 연결
  • 시스템 확장성 및 유지보수성 향상

2. 구조와 동작 원리

기본 구조

클라이언트 → Target 인터페이스
                 ↑
            Adapter ← Adaptee (호환되지 않는 기존 객체)
  • Target: 클라이언트가 기대하는 인터페이스
  • Adaptee: 기존 또는 외부 시스템의 실제 기능을 가진 객체
  • Adapter: Adaptee의 기능을 감싸서 Target처럼 보이게 해주는 클래스

3. 예시 코드 (Java 스타일)

// 클라이언트가 기대하는 인터페이스
public interface MediaPlayer {
    void play(String filename);
}

// 기존 시스템 또는 외부 API
public class LegacyAudioPlayer {
    public void playFile(String path) {
        System.out.println("재생 중: " + path);
    }
}

// Adapter
public class AudioPlayerAdapter implements MediaPlayer {
    private final LegacyAudioPlayer legacyPlayer = new LegacyAudioPlayer();

    public void play(String filename) {
        legacyPlayer.playFile(filename);
    }
}

4. 어떤 문제를 해결하기 위해 자주 쓰일까?

  • 외부 라이브러리의 인터페이스가 우리가 쓰는 방식과 다를 때
  • 기존 시스템(레거시 코드)을 리팩터링 없이 유지하면서 새 코드와 연결할 때
  • 다양한 데이터 포맷(JSON, XML 등)을 표준 인터페이스로 맞춰야 할 때

5. 실무 적용 예시

1) 외부 결제 API 연동

  • 카드사마다 결제 API 구조가 다를 경우, 내부에서 사용하는 공통 인터페이스(PaymentGateway)를 만들고, 각 카드사마다 Adapter를 구현하여 연결

2) Spring에서 HandlerAdapter

  • 다양한 타입의 Controller를 일관된 방식으로 처리하기 위해, Spring MVC는 HandlerAdapter를 통해 DispatcherServlet과 실제 Controller를 연결

3) 파일 포맷 변환기

  • 예: CSV, Excel, JSON 데이터를 내부 표준 객체로 변환하는 Adapter 구성

5.5. Adapter 패턴과 API Gateway의 관계

API Gateway는 여러 마이크로서비스의 진입점을 통합하여 클라이언트와 서버 간의 요청을 중재하는 역할을 합니다.

이 구조는 Adapter 패턴과 매우 유사한 목적을 가지고 있습니다.

  Adapter 패턴 API Gateway
역할 코드 단위의 인터페이스 변환 네트워크 레벨의 요청 라우팅 및 변환
목적 서로 다른 시스템 간 호환성 확보 여러 API를 통합된 진입점으로 제공
범위 클래스/객체 설계 패턴 시스템/아키텍처 계층 구성 요소

예를 들어, 클라이언트가 /pay로 요청을 보냈을 때 API Gateway가 내부적으로 /kakao, /naverpay 등의 실제 서비스로 요청을 라우팅해주는 방식은, 내부의 다양한 서비스 구조를 클라이언트에 맞춰 추상화해준다는 점에서 Adapter와 동일한 설계 철학을 따릅니다. 따라서 API Gateway는 실질적으로 Adapter 패턴을 아키텍처 레벨에서 구현한 사례라고 볼 수 있습니다.


장점 단점
기존 코드 변경 없이 시스템 통합 가능 Adapter 클래스가 많아질 수 있음
레거시 코드 재사용 가능 설계가 복잡해질 수 있음
인터페이스 호환성 확보 성능 이슈 발생 가능성 (간접 호출 등)