어댑터 패턴
- 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴
- 서로 다른 인터페이스를 가진 두 클래스가 협업할 수 있도록 중간에 어댑터를 두어 호환성을 제공하는 구조적 디자인 패턴
- 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하여, 호환되지 않는 인터페이스를 가진 클래스들을 함께 동작하도록 지원
- 주로 레거시 코드를 새로운 시스템에서 사용하고자 할 때 유용
- 해외여행 필수품인 플러그 어댑터를 생각하면 이해하기 쉬움
주요 구성 요소
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 어노테이션을 사용하는 핸들러 메서드를 처리
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의 디자인 패턴 - 백기선 강사님
반응형
'Design Pattern' 카테고리의 다른 글
[디자인 패턴] 컴포짓 패턴 (Composite Pattern) (0) | 2024.06.22 |
---|---|
[디자인 패턴] 브릿지 패턴 (Bridge Pattern) (0) | 2024.06.22 |
[디자인 패턴] 프로토타입 패턴 (Prototype Pattern) (0) | 2024.06.22 |
[디자인 패턴] 빌더 패턴 (Builder Pattern) (0) | 2024.06.21 |
[디자인 패턴] 추상 팩토리 패턴 (Abstract Factory Pattern) (0) | 2024.06.18 |