Adapter Pattern

2025. 10. 19. 00:46·🧊Unity Basic/디자인패턴

어댑터 패턴 ( Adapter Pattern )

프로그램 제작이나 유지보수 시에는 다양한 상황을 마주할 수 있다.

기존의 코드를 변경시키지 않으면서도 다형성을 접목해 여러 객체들을 다룰 수 있어야 한다.

다른 디자인패턴과 마찬가지로 구현 코드에 집중하기 보다는 패턴의 본질에 집중하고

다양한 방식으로 구현될 수 있음을 인지해야 한다.

어댑터 패턴은 C# 개발에서도 굉장히 자주 등장하는 패턴이다.

서로 맞지 않는 코드들을 연결해서 함께 작동하게 만드는 다리 역할을 하는 패턴이다.

 

서로 호환되지 않는 인터페이스를 가진 클래스들을 연결 ( 호환 ) 시켜주는 중간 변환기 ( bridge ) 역할의 디자인 패턴이다

이미 존재하는 코드 ( 또는 라이브러리 ) 를 수정하지 않고 , 새로운 시스템과 연결해서 함께 작동하도록 만드는 구조이다.

▲ 이해하기 쉽게 비유

  • 콘센트 어댑터 ( 돼지코 ) 를 생각하면 이해하기 쉽다
  • 한국 ( 220V ) 을 사용하는 콘센트에 미국 ( 110V ) 전자제품의 플러그를 꽂을 수 없다.
  • 하지만 돼지코 어댑터를 끼우면 플러그의 모양은 그대로 유지하면서 전기만 연결이 가능하게 만들어준다.

코드 세계의 어댑터 패턴도 이와 같다.

이미 만들어진 코드 구조 ( 인터페이스 ) 가 다르지만 , 그걸 중간에서 번역해주는 클래스를 둬서 함께 작동시키는 것이다.

 

 

 

어댑터 패턴의 장점과 단점

장점

  • 기존 코드를 수정하지 않기 때문에 해당 코드가 변경 불가능하거나 업데이트 될 때에도 대응할 수 있다.
  • 최소한의 변경으로 기존 코드를 재사용 할 수 있다

 

단점

  • 약간의 성능 저하가 발생한다 ( 물론 , 이슈가 되지 않을 만큼 미비한 성능 저하이다 )

 

사용하면 좋을 상황

  • 기존 코드가 변경 불가능하거나 , 업데이트를 통해 기존 코드의 내용 변경이 우려될 때
  • 레거시 코드임에도 해당 코드를 사용하는 것이 효율적일 때

 

 

 

어댑터 패턴의 구조

이름 역할 설명
Target ( 목표 인터페이스 ) 클라이언트가 기대하는 인터페이스 새 시스템이 원하는 함수 형식
Adaptee ( 적응 대상 ) 기존 코드 또는 외부 라이브러리 인터페이스가 달라서 직접 사용할 수 없는 대상
Adapter ( 어댑터 ) 변환 중개자 Adaptee 의 인터페이스를 Target 인터페이스로 바꿔주는 클래스

 

 

 

예시 코드

▼ MonsterManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterManager : MonoBehaviour
{
   [SerializeField] private Zombie _zombie;
   [SerializeField] private Alien _alien;

   private List<IMonster> _monsters = new List<IMonster>();

   public void Start()
   {
       _monsters.Add(new ZombieAdapter(_zombie));
       _monsters.Add(new AlienAdapter(_alien));

       foreach (var mon in _monsters)
       {
           mon.Attack();
       }
   }
}

 

 

▼ Zombie.cs

public class Zombie : MonoBehaviour
{
   public void Bite()
   {
       Debug.Log("Zombie bite!");
   }
}

 

 

▼ Alien.cs

public class Alien : MonoBehaviour
{
   public void Shoot()
   {
       Debug.Log("Alien shoot!");
   }
}

 

코드 구조 요약

  • MonsterManager 는 여러 몬스터를 한 리스트 ( List<IMonster> ) 로 관리하고 있다.
  • 하지만 Zombie 와 Alien 은 서로 다른 클래스이다.
    각각 Bite( ) 와 Shoot( ) 이라는 서로 다른 메서드명을 사용하고 있다.
  • 두 클래스는 공통 인터페이스 ( IMonster ) 를 직접 구현하지 않은 상태이다.

 

작성자의 핵심 의도

  • 서로 다른 인터페이스 ( 메서드 구조 ) 를 가진 클래스를 하나의 공통 타입으로 다루고 싶다
  • Zombie 는 Bite( ) 로 공격하고 , Alien 은 Shoot( ) 으로 공격하지만
  • 게임 매니저 입장에서는 이 둘을 Attack( ) 이라는 공통 메서드로 호출하고 싶다.

 

어댑터 패턴을 사용하려는 이유

현재 Zombie 와 Alien 은 구조가 달라서 이렇게 하지 못한다.

List<IMonster> monsters = new List<IMonster>();
monsters.Add(new Zombie()); // Zombie 는 IMonster 아님
monsters.Add(new Alien()); // Alien 도 IMonster 아님

그래서 어댑터 ( Adapter ) 라는 중간 클래스를 만들어 각각 IMonster 로 감싸준다. ( wrap )

 

 

완성된 어댑터 코드

public interface IMonster
{
   public void Attack();
}

public abstract class Adapter<T> : IMonster
{
   protected T Adaptee;

   public Adapter(T t)
   {
       Adaptee = t;
   }

   public abstract void Attack();
}

public class ZombieAdapter : Adapter<Zombie>
{
   public ZombieAdapter(Zombie z) : base(z)
   {
   }

   public override void Attack()
   {
       Adaptee.Bite();
   }
}

public class AlienAdapter : Adapter<Alien>
{
   public AlienAdapter(Alien a) : base(a)
   {
   }

   public override void Attack()
   {
       Adaptee.Shoot();
   }
}

 

▼ 전체 설계 의도

서로 다른 몬스터 클래스 ( Zombie , Alien ) 의 공격 메서드를 IMonster.Attack( ) 이라는 통일된 인터페이스로 묶기 위해 유연하고 재사용 가능한 디자인패턴 어댑터 구조를 사용했다.

다양한 몬스터를 하나의 규칙으로 제어하려는 목적이다.

 

 

구조적 설계 분석

1. IMonster

공통 인터페이스

public interface IMonster
{
    void Attack();
}
  • 모든 몬스터는 공격 ( Attack ) 이라는 행위를 가진다는 계약 ( Contract ) 을 정의한다.
  • MonsterManager 는 오직 이 인터페이스에만 의존한다
  • ( 구체적인 몬스터 클래스는 몰라도 된다 )

 

 

2. Adapter<T>

제네릭 기반 어댑터 추상 클래스

public abstract class Adapter<T> : IMonster
{
    protected T Adaptee; // 실제 적응 대상 객체

    public Adapter(T t)
    {
        Adaptee = t;
    }

    public abstract void Attack(); // 구체 서브클래스에서 구현
}
  • 어댑터 클래스의 공통 구조를 제네릭 ( Generics ) 으로 일반화한다.
  • ZombieAdapter , AlienAdapter , OrcAdapter , RobotAdapter 등
    새로운 어댑터가 생겨도 공통 패턴을 복사 붙여넣기 없이 그대로 사용 가능하다
  • 코드 중복 최소화 , 유지보수 용이 , 어댑터의 역할이 명확히 분리되는 이점이 있다.

 

3. ZombieAdapter , AlienAdapter

구체 어댑터 구현

public class ZombieAdapter : Adapter<Zombie>
{
    public ZombieAdapter(Zombie z) : base(z) { }
    public override void Attack() => Adaptee.Bite();
}

public class AlienAdapter : Adapter<Alien>
{
    public AlienAdapter(Alien a) : base(a) { }
    public override void Attack() => Adaptee.Shoot();
}

각각의 어댑터가 자신이 감싼 클래스의 고유 메서드를 Attack( ) 으로 변환 ( mapping ) 시킨다.

원래 클래스 원래 메서드 어댑터를 통해 변환된 메서드
Zombie Bite( ) Attack( )
Alien Shoot( ) Attack( )

 

 

4. MonsterManager

클라이언트 ( 사용자 )

_monsters.Add(new ZombieAdapter(_zombie));
_monsters.Add(new AlienAdapter(_alien));

foreach (var mon in _monsters)
{
    mon.Attack();
}
  • MonsterManager 는 이제 Attack( ) 만 알고 있으면 된다
  • 내부에 Zombie 가 있든 , Alien 이 있든 상관없이 동일한 인터페이스로 호출이 가능하다

 

디자인 패턴 관점

설계 목표 코드 구현 방식
1. 인터페이스 통일 IMonster 로 공통 규격 정의
2. 기존 클래스 수정 없이 확장 Zombie , Alien 은 수정하지 않는다
3. 유연한 확장성 확보 Adapter<T> 제네릭 구조로 새로운 몬스터에도 대응 가능
4. 의존성 역전 ( DIP ) MonsterManager 는 구체 클래스가 아닌 인터페이스 ( IMonster ) 에 의존
  • 객체지향 설계의 대표 원칙인 OCP 를 잘 지킨 구조이다.
  • OCP ( Open / Closed Principle ) 확장에는 열려 있고 , 수정에는 닫혀 있다

 

 

정리

어댑터 패턴은 서로 다른 인터페이스를 가진 객체들을 하나의 공통 인터페이스로 묶어

동일한 방식으로 다룰 수 있게 해주는 패턴이다

'🧊Unity Basic > 디자인패턴' 카테고리의 다른 글

Adapter Pattern 핵심 코드  (0) 2025.10.24
Observer Pattern  (0) 2025.10.21
Singleton 과 Generic  (0) 2025.10.21
Singleton Pattern  (0) 2025.10.20
Design Pattern  (0) 2025.10.18
'🧊Unity Basic/디자인패턴' 카테고리의 다른 글
  • Observer Pattern
  • Singleton 과 Generic
  • Singleton Pattern
  • Design Pattern
DevHoChan
DevHoChan
맨땅에서 시작하는 코딩 도전
  • DevHoChan
    Debugging Life
    DevHoChan
  • 전체
    오늘
    어제
    • 분류 전체보기 (374)
      • 🕹️Game Life (1)
      • 🖥️Computer Science (5)
      • 📖TIL (141)
        • 🔥Projects (16)
        • 💡DevTips (5)
        • 🤔발생한 문제와 해결 (5)
        • 🔮Unity Graphics (5)
        • 🎤Interview (3)
        • ✅CodingTest (9)
      • 🚀Game Release (4)
      • 🧊Unity Basic (58)
        • 📌용어 사전 (1)
        • 에디터&인터페이스 (3)
        • 디버그 (1)
        • 라이프사이클 (4)
        • 게임오브젝트 (4)
        • 프리팹 (1)
        • 오브젝트풀링 (4)
        • 애트리뷰트 (2)
        • 트랜스폼 (4)
        • 물리&충돌 (1)
        • 프레임&델타타임 (4)
        • 코루틴&이벤트 (7)
        • 수학&보정함수 (3)
        • 디자인패턴 (9)
        • UGUI (3)
        • 벡터 ( Vector ) (3)
        • 씬 ( Scene ) (2)
        • 데이터 관리 (2)
      • ⭐C Sharp (99)
        • 📌용어 사전 (1)
        • 📌문법 사전 (6)
        • 메모리 관리 (3)
        • 00. 문법 (17)
        • 01. 변수 (3)
        • 02. 자료형 (2)
        • 03. 연산자 (6)
        • 04. 조건문 (2)
        • 05. 반복문 (2)
        • 06. 배열 (3)
        • 07. 메서드(함수) (7)
        • 08. 열거형 (3)
        • 09. 구조체 (2)
        • 10. 참조 (2)
        • 11. 객체 지향 (11)
        • 12. 델리게이트 (3)
        • 13. 디자인 패턴 (7)
        • 14. LINQ (1)
        • 📂▼자료구조 (2)
        • 15-1. 제네릭 (3)
        • 15-2. 배열 (4)
        • 15-3. 리스트 (2)
        • 15-4. 스택과 큐 (2)
        • 15-5. 딕셔너리 해시테이블 (2)
        • 15-6. 트리와 그래프 (3)
      • 📊Algorithm (16)
        • BigO (2)
        • 정렬 (4)
        • 셔플 (2)
        • 탐색 (6)
        • 최적화 (1)
      • 📝Game Design (16)
      • 🤖​AI Tools (12)
        • AI 리뷰 분석 (6)
        • Player2 (0)
        • 3D 모델링 (1)
        • 2D 스프라이트 (0)
        • 이미지 (2)
        • 사운드 (1)
        • 동영상 (1)
        • 문서 (1)
      • 🌍Network (6)
      • 🌱Github (11)
        • 기본 개념 (7)
        • 명령어 (1)
        • 도구 활용 (1)
      • ⚙️Visual Studio (5)
        • 🔧설치 및 환경설정 (2)
        • ⌨️HotKey (1)
        • 🚨디버깅 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    디자인패턴
    자료형
    문법
    부트캠프
    자료구조
    til
    기획
    c#
    게임기획
    unity
    algorithm
    유니티
    GitHub
    메모리관리
    OOP
    게임디자인
    CodingTest
    객체지향
    csharp
    gamedesign
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
DevHoChan
Adapter Pattern
상단으로

티스토리툴바