[구조 패턴] Chapter 6-1. Adapter Pattern : 패턴 소개

 

✍️ 어댑터 패턴, 패턴 소개

어댑터 패턴은 일상생활에서도 흔히 찾아볼 수 있는데, 220V 코드를 110V 콘센트에 꽂을 때 흔히 돼지코라고 불리는 어댑터를 사용해 본 경험이 있을 것이다. 바로 이 돼지코가 어댑터 패턴과 유사한 실생활 사례라고 할 수 있다.

 

이제 소프트웨어적 측면에서 어댑터 패턴을 설명하면, Client가 사용하는 Interface는 정해져있는데 내가 작성한 코드(Adaptee)는 해당 Interface를 따르지 않을 때 ClientAdaptee 사이의 간극을 Adapter로 메꿔서 Adaptee를 재사용할 수 있도록 하는 패턴이다.

 

정리하면 '기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴이다.'

 

언제나 그렇듯... 말로는 너무 어렵다 코드를 보자.

 

🍊 어댑터 패턴, 적용 전 코드

코드를 살펴보기 전에, UserDetails, UserDetailsService, LoginHandler security 패키지에서 제공하는 코드로 라이브러리 코드라고 생각해도 좋다.

 

여기, 유저의 이름과 패스워드를 반환하는 메서드를 추상화한 UserDetails 인터페이스가 있고 

public interface UserDetails {
    String getUsername();

    String getPassword();
}

 

username을 받아서 UserDetails를 반환하는 메서드를 추상화한 UserDetailsService 인터페이스가 있다.

public interface UserDetailsService {
    UserDetails loadUser(String username);
}

 

그리고 UserDetailsUserDetailsService를 사용해서 Login을 처리하는 LoginHandler가 있다.

login 메서드는 굉장히 간단한데, UserDetailsService에서 username으로 읽어와서 UserDetails의 패스워드가 일치한지 판단해서 로그인을 처리한다.

public class LoginHandler {
    private UserDetailsService userDetailsService;

    public LoginHandler(UserDetailsService userDetailsService){
        this.userDetailsService = userDetailsService;
    }

    public String login(String username, String password){
        UserDetails userDetails = userDetailsService.loadUser(username);

        if(userDetails.getPassword().equals(password)){
            return userDetails.getUsername();

        }else{
            throw new RuntimeException();
        }
    }
}

 

Account 클래스는 일반적으로 우리가 애플리케이션을 만들 때 유저 정보를 담는 클래스라고 생각하면 된다. 

@Data
public class Account {
    private String name;
    private String password;
    private String email;
}
public class AccountService {
    public Account findAccountByUsername(String username){
        Account account = new Account();
        account.setName(username);
        account.setPassword(username);
        account.setEmail(username);

        return account;
    }

    public Account createNewAccount(String username){
        // TODO, blah blah blah
        return new Account();
    }
}

 

다시 말하지만 UserDetails, UserDetailsService, LoginHandler는 security 패키지에서 제공하는 코드로 다른 애플리케이션에서도 공통으로 사용하는 일종의 라이브러리 코드고, AccountAccountService는 애플리케이션에 구현이 따라 달라지는 코드로 이 둘의 직접적인 관계는 없다

 

어찌 됐든, security 패키지가 제공하는 login 기능을 우리가 정의한 Account와 AccountService를 가지고도 돌아가도록 만드는 것이 목적이다.

 

✨ 어댑터 패턴, 코드 정리

그림과 함께 정리해 보자.

 

security 패키지가 제공하는 login 로직은 Client에 해당한다.

 

Client는 UserDetails와 UserDetailsService라는 정해진 인터페이스(Target)를 사용한다.

 

애플리케이션에서 정의한 Account와 AccountService는 Adaptee에 해당한다.

 

지금까지의 코드에서 비어있는 건 바로 Adapter로 Client와 Adaptee의 간극을 Adpater를 추가해서 메꿔줄 수 있다! 

 

 

적용 코드는 다음 포스팅에서...

 

 

인프런의 백기선님의 강의 코딩으로 학습하는 GoF의 디자인 패턴을 참고해서 작성했습니다.

 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com