본문 바로가기
LV3_Advanced/GOF 패턴

Adapter (어댑터) - 구조 패턴 #2

by 하타라시 2026. 2. 24.

목차

💡
  • 왜 어댑터 패턴을 사용해야 하는가
  • 설계도는 어떻게 생겼나?
  • 실제로 어떻게 구현하나?
  • 장점과 단점은 무엇인가?

왜 어댑터 패턴을 사용해야 하는가?

호환되지 않는 인터페이스를 가진 객체들을 변환해 주기 위해 사용합니다. 기존 코드를 수정할 수 없거나 수정하고 싶지 않을 때, 중간에서 연결해 주는 역할을 합니다.

예를 들어, 실수로 220V 전용 충전기를 들고 110V를 사용하는 일본에 갔다고 가정하겠습니다. 이 때, 충전기를 그대로 꽂을 수 없으므로, 어댑터를 끼워서 규격을 호환되게 만드는 것과 같은 이치입니다.

설계도는 어떻게 생겼나?

  • Target
    • 클라이언트가 사용하길 기대하는 표준 인터페이스
    • JPN에서 사용하므로 110V를 의미합니다.
  • Adeptee
    • 기존에 있던 호환되지 않는 클래스나 객체입니다.
    • KOR에서 사용하는 220V를 의미합니다.
  • Adepter
    • Adaptee를 Target에 맞게 변환해주는 중간 단계입니다.
    • 이미지에서는 220V를 110V로 변환하는 역할입니다.

실패

실제로 어떻게 구현하나?

인터페이스 및 기존 클래스

// 1. 클라이언트(일본 콘센트)가 사용하길 기대하는 110V 인터페이스 (Target)
public interface Electronic110V {
    void powerOn();
}

// 2. 이미 가지고 있는 220V 한국 충전기 (Adaptee)
public class Charger220V {
    public void charge() {
        System.out.println("220V 충전기로 기기 충전을 시작합니다.");
    }
}

어댑터 클래스 코드

// 3. 220V 기기를 110V 콘센트에 맞게 바꿔주는 어댑터 클래스 (Adapter)
public class PlugAdapter implements Electronic110V {
    
    private Charger220V charger220V; // 호환되지 않는 기존 객체를 변수로 가짐
    
    // 생성자를 통해 사용할 220V 기기를 주입받음
    public PlugAdapter(Charger220V charger220V) {
        this.charger220V = charger220V;
    }

    // 🌟 핵심: 클라이언트(110V 콘센트)가 110V 방식(powerOn)으로 호출하면, 
    // 어댑터가 내부적으로 220V 기기의 방식(charge)으로 변환해서 실행해줌
    @Override
    public void powerOn() {
        System.out.println("어댑터 변환 중: 110V 전원 입력 -> 220V 기기로 출력");
        charger220V.charge(); 
    }
}

사용 예시

public class Main {
    public static void main(String[] args) {
        // 1. 220V 한국 충전기 준비 (Adaptee)
        Charger220V myCharger = new Charger220V();
        
        // 2. 110V 규격에 맞추기 위해 어댑터에 220V 충전기를 연결 (Adapter)
        Electronic110V adapter = new PlugAdapter(myCharger);
        
        // 3. 클라이언트(일본 110V 콘센트)는 110V 인터페이스만 알고 있으면 됨!
        connectTo110V(adapter);
    }
    
    // 클라이언트 로직 (오직 110V 인터페이스만 허용하는 콘센트)
    public static void connectTo110V(Electronic110V electronic) {
        electronic.powerOn();
    }
}

장점과 단점은 무엇인가?

장점

  • 기존 코드 재사용 및 보호
    • 호환되지 않는 기존 클래스나 외부 라이브러리의 코드를 전혀 수정하지 않고도 새로운 시스템에서 사용할 수 있습니다,
  • SRP(단일 책임 원칙)와 OCP(개방 폐쇄 원칙) 준수
    • 기존 로직과 데이터 변환 로직을 분리할 수 있으며, 기존 코드의 흐름을 유지하면서 새로운 어댑터만 추가하면 됩니다.

단점

  • 구조의 복잡성 증가
    • 시스템에 새로운 인터페이스와 어댑터 클래스가 다수 추가되어야 하므로 전반적인 코드의 복잡도가 증가합니다.
    • 때로는 기존 클래스를 수정하는게 더 간단할 수도 있습니다.