티스토리 뷰

반응형

흔히 개발하다보면 디자인 패턴에 대한 이야기를 쉽게 접할 수 있는데요, 어떠한 구조로 개발을 하느냐는 글을 쓸때나 건물을 지을때나 설계 관점에서 굉장히 중요합니다. 건축물을 예를 들어 잠실타워같은 모습의 건물을 짓기위해선 어떤 공법을 사용하는게 좋을까요? 100층이 넘는 건물을 지을 때 비단 5층짜리 건물을 지을 때 공법과는 분명 다른 점들이 있을 것입니다. 그 반대의 경우도 마찬가지일 것이구요. 앞으로 디자인 패턴 이야기도 해보려고 하는데요, 디자인 패턴하면 떠오르는 패턴은 여러분은 어떤 것들이 있으신지요? 가장 많이 접하는 싱글톤! 이 있겠지만 오늘은 어답터 패턴에 대해서 이야기해보려고 합니다.

어답터 패턴(Adapter Pattern)

위키피디아의 정의에 따르면 어답터 패턴은 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴으로, 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 작동하도록 해줍니다.

어답터 패턴은 2가지 형태로 구현할 수 있는데요, 오브젝트 어답터 형태와 클래스 어답터 형태입니다. 관련 내용은 제 블로그가 아니어도 쉽게 찾아볼 수 있으니 위키피디아 내용의 예제를 발췌하도록 하겠습니다.

오브젝트 어답터

# Python code sample
class Target(object):
    def specific_request(self):
        return 'Hello Adapter Pattern!'

class Adapter(object):
    def __init__(self, adaptee):
        self.adaptee = adaptee

    def request(self):
        return self.adaptee.specific_request()

client = Adapter(Target())
print client.request()

Adapter라는 클래스에 Target이라는 오브젝트를 넣어서 request를 사용하고 있죠?

클래스 어답터

/**
 * Java code sample
 */

/* the client class should instantiate adapter objects */
/* by using a reference of this type */
interface Stack<T>
{
  void push (T o);
  T pop ();
  T top ();
}

/* DoubleLinkedList is the adaptee class */
class DList<T>
{
  public void insert (DNode pos, T o) { ... }
  public void remove (DNode pos) { ... }

  public void insertHead (T o) { ... }
  public void insertTail (T o) { ... }

  public T removeHead () { ... }
  public T removeTail () { ... }

  public T getHead () { ... }
  public T getTail () { ... }
}

/* Adapt DList class to Stack interface is the adapter class */
class DListImpStack<T> extends DList<T> implements Stack<T>
{
  public void push (T o) {
    insertTail (o);
  }

  public T pop () {
    return removeTail ();
  }

  public T top () {
    return getTail ();
  }
}

상속을 통해서 활용하고 있는데요. Adapter가 Operation을 사용할 때 이 것이 내부 객체로 오는지 상속을 오는지의 차이가 있을 뿐 동일합니다. 그럼 각 어답터 패턴의 장단점에 대해서 살펴보도록 하겠습니다. 

각 어답터 패턴별 장단점

  • 객체 어답터 패턴
    • 단점 : 어답터 클래스의 대부분의 코드를 구현해야하기 때문에 효율적이지 못하다.
    • 장점 : Composition을 사용하기 때문에 더 유연하다.
  • 클래스 어답터
    • 장점 : 상속을 활용하기 때문에 유연하지 못하다. 다중상속이 지원되는 언어에서만 사용 가능하다.
    • 장점 : 어답터 전체를 다시 구현할 필요가 없다.

어답터 패턴의 장단점

  • 장점 
    • 기존 코드를 변경하지 않아도 된다.
    • 기존 코드를 변경하지 않기 때문에 클래스 재활용성을 증가 시킬 수 있다.
  • 단점
    • 구성요소를 위해 클래스를 증가시켜야 하기 때문에 복잡도가 증가할 수 있다.
    • 클래스 어답터의 경우 상속을 사용하기 때문에 유연하지 못하다.
    • 반면 객체 아답터의 경우는 대부분의 코드를 다시 작성해야 하기 때문에 효율적이지 못하다.

여기까지 어답터 패턴에 대해서 주요사항들에 대해서 정리해 보았는데요, 조금 더 나가서 실제 용례에 대해서 이야기해보도록 하겠습니다. 우리는 개발할때 어떠한 오픈소스를 쉽게 설치해서 사용하기도 하지만 그 오픈소스는 나의 프로젝트에 찰싹 달라붙지 않을 수도 있습니다. 어떤 뜻이냐면 오픈소스의 경우 자체적으로 이를 래핑을 해줄 필요성이 있고, 만약 그렇지 않고 내재화를 한다면 오픈소스를 지속적으로 포팅해야하는 일들이 수반되게 되어지는데요, 오픈소스의 장점은 오픈소스의 진영에서 지속적으로 개발하고 업그레이드하는 롤을 갖고 있으니, 내가 사용하는 프로젝트에서 이를 쉽게 가져다가 사용되도록 하는 것이 좋습니다. 

오픈 소스의 인터페이스 공용화

어떤 플랫폼이나 프레임워크를 예를 들어서, 각각의 프레임워크끼리는 룰을 가지고 인터페이스를 설계합니다. 그래야 하나의 플랫폼 안에서 프레임워끼리 유기적으로 소통을 하겠지요? 다만 새로운 오픈 소스를 프레임웍화 하여서 동작시킨다면 자체적으로 마련한 이 룰을 정확히 따라하고 있지는 않을 것입니다. 룰 자체는 쉽게 네이밍 컨벤션도 있을거고, 메모리를 엑세스하는 방법도 있을 것이고요 플랫폼이 단단해 질 수록 이러한 리소스들을 관리하는 주체를 하는 것도 단단해져 있기 때문에 이를 중앙에서 통제하고 새로운 오픈소스라도 이를 따라주어야 플랫폼 자체가 점점 완성도가 높아집니다. 다만 오픈소스 자체 코어를 수정하면서까지 이를 하는 것은 오픈소스 버전이 업그레이드 되어 있을때 포팅하는 일들이 많아지는 또 다른 웍이 되는 것이죠, 저는 이럴 때 어답터 패턴을 사용하면 좋겠다고 생각하고 있습니다. 구체적으로 제가 했던 예를 들어 볼께요.

저는 다커라는 컨테이너 관리하는 오픈소스를 저희 플랫폼에 넣으려고 하였습니다. 다만 각 프레임워에서 다커가 제공하는 인터페이스를 사용하기 위해서는 어떻게 해야할까요? 다커는 이미 REST를 통해 API 제공하고 있고 CLI를 통해서도 다커 엔진에 접근하여 컨테이너를 관리할 수 있도록 하고 있습니다. 그리고 굉장히 많은 기능들이 있죠. 다만 플랫폼에서는 이에 대한 기능을 모두 오픈 시킬 필요는 없습니다. 이유는 다커자체가 시스템 권한을 가지고 있는 것이기도 해서 우선은 가볍게 몇가지 기능만 오픈하되 핫한 오픈소스이다보니 지속적인 업그레이드를 대응할 필요가 있었습니다. 따라서 docker-adapter 라는 패키지를 만들고, 다른 프레임웍에서는 docker-adapter 패키지와 소통해서 다커 엔진의 기능을 이용할 수 있도록 하였습니다. 물론 이를 이어주기 위한 개발들이 이어졌지만, 다커 엔진을 오픈소스로 퓨어하게 가져가면서 내부에 있는 프레임웍을 위해 기능을 제공할 수 있었습니다.

종합적으로 봤을때, 오픈소스의 성향에 따라 어답터 패키지가 적용될 수 있는 구조도 있고 아닐 수도 있습니다. 같은 프레임웍안에 존재하게 오픈소스, 라이브러가 들어갈 수도 있고, 자체적으로 프레임웍구조로 가져갈 수 도 있으며 안드로이드처럼 아에 전체적으로 들어가서 기존 플랫폼과 통신하는 경우도 있을 것입니다. 어답터 패키지는 이를 모두 커버하는 패턴이기 보다는 서두에 설명한대로 인터페이스 호환성 문제를 해결할 수 있는데 집중하고 있습니다. 마치 아이폰 이어폰 연결을 위해 라이트닝 잭을 위한 컨버터 처럼요. 여러분도 각각의 사례에서 활용하시면서 깊이있게 어답터 패턴에 대해서 깊숙히 알아가셨으면 합니다.

반응형
댓글