Design Pattern

[디자인 패턴] 어댑터 패턴 (Adapter Pattern)

꾸준함. 2024. 6. 22. 11:49

어댑터 패턴

  • 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴
  • 서로 다른 인터페이스를 가진 두 클래스가 협업할 수 있도록 중간에 어댑터를 두어 호환성을 제공하는 구조적 디자인 패턴
  • 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하여, 호환되지 않는 인터페이스를 가진 클래스들을 함께 동작하도록 지원
  • 주로 레거시 코드를 새로운 시스템에서 사용하고자 할 때 유용
  • 해외여행 필수품인 플러그 어댑터를 생각하면 이해하기 쉬움

 

https://www.geeksforgeeks.org/adapter-pattern/

 

주요 구성 요소

 

1. Target 인터페이스

  • 클라이언트가 사용하려고 하는 인터페이스

 

2. Adapter

  • 타겟 인터페이스를 구현하고 어댑티(Adaptee)의 인터페이스를 호출하여 중간 역할

 

3. Adaptee

  • 변환되어야 할 기존 클래스

 

4. Client

  • 타겟 인터페이스를 사용하는 객체

 

어댑터 패턴 구현 예시 (Spring Security)

  • Spring Security에서 어댑터 패턴을 활용하여 기존의 사용자 정보 객체를 UserDetails 인터페이스와 호환되도록 만들 수 있음

 

1. UserDetails 인터페이스

  • Spring Security에서 사용자 정보를 표현하는 인터페이스

 

 

2. 애플리케이션에서 사용하는 User 클래스 (Adaptee)

  • 기존 시스템에서 사용되고 있는 사용자 정보 클래스

 

 

3. UserDetailsAdapter 클래스 (Adapter)

  • 기존 사용자 클래스를 UserDetails 인터페이스와 호환되도록 변환하는 어댑터 클래스

 

 

정리

  • UserDetailsAdapter 클래스는 UserDetails 인터페이스를 구현하고, 기존의 User 객체를 내부에 두어, Spring Security에서 기대하는 UserDetails 인터페이스로 변환시키며 이를 통해 Spring Security와 기존 사용자 클래스를 호환시킬 수 있음
  • 이처럼 어댑터 패턴은 기존 클래스와 새로운 인터페이스를 연결해 주는 중요한 역할을 하며, Spring Security의 UserDetails 인터페이스를 사용할 때도 유용하게 활용할 수 있음

 

어댑터 패턴 장단점

 

장점

  • 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 재사용 가능 (SOLID 원칙의 OCP 원칙)
  • 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리 가능 (SOLID 원칙의 SRP 원칙)

 

단점

  • 다른 디자인 패턴들과 마찬가지로 클래스가 늘어남에 따라 관리 포인트가 늘어나 복잡도가 증가할 수 있음
    • 이를 방지하기 위해 기존 코드가 해당 인터페이스를 구현하도록 수정하는 방법도 있지만 이는 SOLID의 단일 책임 원칙을 위반하는 행위
    • 트레이드오프 관계를 고려하여 설계할 필요성 있음

 

실무에서 쓰이는 어댑터 패턴

 

1. Spring Security

  • 앞서 예시에서 간략하게 설명했으므로 생략

 

2. 자바 컬렉션

  • Arrays.asList(T ...): 가변인자인 배열을 매개변수로 넘기고 List를 반환받음
  • Collections.enumeration(String): 문자열을 매개변수로 넘기고 Enumeration을 반환받음
  • Collections.list(Enumeration): Enumeration을 매개변수로 넘기고 List를 반환받음

 

 

3. Spring MVC의 HandlerAdapter

  • 다양한 형태의 Handler 코드를 스프링 MVC가 실행할 수 있는 형태로 변환해 주는 어댑터용 인터페이스
  • Spring MVC에서 여러 가지 HandlerAdapter 구현체가 제공됨
    • SimpleControllerHandlerAdapter: Controller 인터페이스를 구현한 핸들러를 처리
    • RequestMappingHandlerAdapter: @RequestMapping 어노테이션을 사용하는 핸들러 메서드를 처리

 

https://jaimemin.tistory.com/1887

 

 

DispatcherServlet 관점에서의 어댑터 패턴

  • DispatcherServlet은 Spring MVC의 프론트 컨트롤러로 모든 HTTP 요청을 처리하고 적절한 핸들러를 전달하는 역할
  • DispatcherServlet은 여러 가지 핸들러를 처리할 수 있어야 하며 이때 어댑터 패턴을 사용하여 다양한 유형의 핸들러를 통합적으로 관리
    • Target 인터페이스: HandlerAdatper 인터페이스
    • Adaptee: 다양한 유형의 핸들러로 @Controller나 Controller 인터페이스를 구현한 클래스
    • Adatper: HandlerAdapter 인터페이스를 구현한 클래스들
    • Client: DispatcherServlet으로 다양한 핸들러를 일관된 방식으로 호출

 

DispatcherServlet 일부 발췌


 

동작 과정

  • DispatcherServlet이 HTTP 요청 수신
  • HandlerMapping을 사용하여 요청을 처리할 핸들러 조회
    • DispatcherServlet은 HandlerAdapter 목록을 순회하며 supports 메서드를 통해 주어진 핸들러를 처리할 수 있는 HandlerAdapter 조회

 

  • 적절한 HandlerAdapter를 handle 메서드를 통해 실행
  • ModelAndView를 통해 결과를 반환하고 ViewResolver를 사용하여 뷰를 렌더링

 

참고

코딩으로 학습하는 GoF의 디자인 패턴 - 백기선 강사님

반응형