개발자로 후회없는 삶 살기

디자인 패턴 PART.퍼사드 패턴 본문

[백엔드]/[Java | 학습기록]

디자인 패턴 PART.퍼사드 패턴

몽이장쥰 2023. 8. 21. 14:28

서론

※ 이 포스트는 다음 강의의 학습이 목표임을 밝힙니다.

https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard

 

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

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

www.inflearn.com

 

본론

- 패턴 소개

퍼사드의 단어뜻은 건물의 입구를 바라보는 외벽을 뜻합니다. 입구를 보면 내부 내용을 알 수는 없습니다. 또한 그 안에 들어가도 또 다른 레이어로 배관, 전기가 어떻게 연결되어있는지 알 수 없습니다. 퍼사드로 모든 디테일한 것을 숨기는 것입니다.

 

- 코드

public class Client {

    public static void main(String[] args) {
        String to = "keesun@whiteship.me";
        String from = "whiteship@whiteship.me";
        String host = "127.0.0.1";

        Properties properties = System.getProperties();
        properties.setProperty("mail.smtp.host", host);

        Session session = Session.getDefaultInstance(properties);

        try {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject("Test Mail from Java Program");
            message.setText("message");

            Transport.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

자바로 메일을 보내는 코드입니다. 의존성이 굉장히 많습니다. 클라이언트에 세션, 프로퍼티스, 예외 등 의존성이 생깁니다. loosely coupled라는 말은 의존성이 루즈하다는 것으로 타이트할 수록 여러모로 단점이 많기에 우리는 의존성을 굉장히 유연한 구조를 만들고 싶어합니다. 그래서 solid 원칙과 패턴을 배우는 것입니다. 

 

현재 코드는 타이트한 코드인데 퍼사드를 적용해서 코드를 개선할 것입니다.

 

=> 구조

복잡한 의존성들을 퍼사드라는 클래스를 사용해서 클라이언트가 서브 시스템 의존성을 직접 가지는게 아니라 중간에 복잡한 서브 시스템을 압축시켜서 클라이언트는 퍼사드만 사용하고 복잡한 디테일은 퍼사드 뒤로 다 숨기는 것입니다.

 

- 패턴 적용

의존성을 줄여보겠습니다. 이러한 코드를 추상화하려면 "어떻게 추상화를 할까?" 분석을 잘 해야합니다. 잘 보면 메세지를 보내는 코드가 있습니다. 메일을 보내는 클래스와 설정, 메세지를 나눠볼까 합니다.

 

이메일 센더
이메일 메세지
이메일 셋팅

 

public class EmailSender {
    private EmailSettings emailSettings;
    
    public EmailSender(EmailSettings emailSettings) {
        this.emailSettings = emailSettings;
    }
    
    public void sendEmail(EmailMessage message) {
        
    }
}

이렇게 나눠서 센더에서 셋팅을 가지고 클래스를 만들도록 할 것입니다. 그리고 sendEmail을 할 때 보낼 메세지를 받도록 합니다. 이제 여기에 클라이언트 코드를 넣을 것인데 호스트 정보는 셋팅에 있고 to, from, 타이틀, sub는 이메일 메세지에 있는게 좋을 것 같습니다.

 

-> 메세지

public class EmailMessage {
    private String from;
    private String to;
    private String subject;
    private String text;

메세지는 from, to, sub, text를 가집니다.

 

-> 셋팅

public class EmailSettings {
    private String host;
    
    public String getHost() {
        return host;
    }
    
    public void setHost(String host) {
        this.host = host;
    }
}

셋팅은 호스트를 가지고

 

// 기존
public void sendEmail(EmailMessage message) {
        String to = "keesun@whiteship.me";
        String from = "whiteship@whiteship.me";
        String host = "127.0.0.1";
    
        Properties properties = System.getProperties();
        properties.setProperty("mail.smtp.host", host);
    
        Session session = Session.getDefaultInstance(properties);
    
        try {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject("Test Mail from Java Program");
            message.setText("message");
        
            Transport.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
    
// 이후
public void sendEmail(EmailMessage emailMessage) {
    Properties properties = System.getProperties();
    properties.setProperty("mail.smtp.host", emailSettings.getHost());

    Session session = Session.getDefaultInstance(properties);

    try {
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress(emailMessage.getFrom()));
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(emailMessage.getTo()));
        message.setSubject(emailMessage.getSubject());
        message.setText(emailMessage.getText());

        Transport.send(message);
    } catch (MessagingException e) {
        e.printStackTrace();
    }
}

OBJ VALUE를 만들고 각각을 추상화했습니다.

 

-> 클라이언트

public class Client {
    public static void main(String[] args) {
        EmailSettings emailSettings = new EmailSettings();
        emailSettings.setHost("127.0.0.1");
    
        EmailSender emailSender = new EmailSender(emailSettings);
        EmailMessage emailMessage = new EmailMessage();
        emailMessage.setFrom("hsb");
        emailMessage.setTo("sang");
        emailMessage.setSubject("오징어게임");
    }
}

그러면 이제 클라이언트는 추상화한 email 셋팅, 센더, 메세지를 사용하도록 코드가 바뀝니다. 이렇게 하면 퍼사드를 만들었고 클라이언트는 퍼사드에 의존합니다. obj를 만들었기에 자체 테스트를 하기 수월해졌습니다. 이메일을 보내는 기능을 여러 곳에서 쓴다고 하면 반복되는 메서드 중복을 개선할 수도 있을 것입니다.

 

- 장, 단점

서브 시스템에 대한 의존성을 한 곳에 몰아둘 수 있습니다. 일종의 리팩토링이라고 볼 수 있습니다. 또한 클라이언트는 프로퍼티스나 세션을 몰라도 되어서 라이브러리에 대한 깊이 있는 학습이 필요없습니다.

Comments