본문 바로가기
Computer Sience/Desgin Pattern

[Design Pattern] 퍼사드(Facade) 패턴

by 제우제우 2024. 10. 28.

퍼사드(Facade) 패턴

facade 뜻 

얼굴, 건물에서는 건물의 얼굴, 즉 주요 전면을 의미한다.

 

복잡한 서브 시스템 의존성을 최소화하는 방법

클라이언트가 사용해야 하는 복잡한 서브 시스템 의존성을 간단한 인터페이스로 추상화 할 수 있다.

퍼사드(Facade) 패턴 before

public class Client {
    public static void main(String[] args) {
        String to = "baejeu@naver.com";
        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();
        }
    }
}

실제 동작하는 코드는 아니다.

 

현재 클라이언트의 메일 전송 코드는 여러가지 문제점이 있다.

메일을 보내기 위한 다양한 설정과 객체 생성 과정이 클라이언트 코드에 포함되어 있어 가독성이 떨어진다.

클라이언트는 메일 전송의 내부 작동방식을 알아야 한다.

 

만약 메일 전송 로직이 변경되거나 추가적인 기능이 필요한 경우, 클라이언트 코드 전체를 수정해야 할 수 있다.

이는 코드의 중복과 유지 보수의 어려움을 초래한다.

 

클라어언트는 jakrata.mail 패키지에 직접 의존하고 있으며, 이는 클라이언트 코드가 이메일 전송의 세부 사항에 강하게 결합되어 있음을 의미한다.

 

이러한 문제들을 facade 패턴을 적용해서 개선해 보자.

퍼사드(Facade) 패턴 after

@Getter @Setter
public class EmailSettings {
    private String host;
}

@Getter @Builder
public class EmailMessage {
    private String to;
    private String from;
    private String subject;
    private String text;
}

@RequiredArgsConstructor
public class EmailSender {
    private final EmailSettings emailSettings;
    public void sentEmail(EmailMessage message){
        Properties properties = System.getProperties();
        properties.setProperty("mail.smtp.host", emailSettings.getHost());
        Session session = Session.getDefaultInstance(properties);
        try {
            MimeMessage mimeMessage = new MimeMessage(session);
            mimeMessage.setFrom(new InternetAddress(message.getFrom()));
            mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(message.getTo()));
            mimeMessage.setSubject(message.getSubject());
            mimeMessage.setText(message.getText());
        }
        catch (MessagingException e){
            e.printStackTrace();
        }
    }
}

 

클라이언트 코드 

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 = EmailMessage.builder()
                .to("baejeu@naver.com")
                .from("whiteship@whiteship.me")
                .subject("제목")
                .text("내용")
                .build();

        emailSender.sentEmail(emailMessage);
    }
}

 

before와 비교했을 때 현재 코드는 어떤 장점이 있을까?

 

먼저 클라이언트 코드를 보면 가독성이 훨씬 더 좋아졌다.

 

클라이언트가 직접 의존하고 있던 jakarta.email 패키지에 대한 의존이 사라졌다. 

의존을 퍼사드인 EmailSender에게 맡겼기 때문이다. 

 

EmailSender는 현재는 클래스지만 인터페이스로 바꾼다면 더욱 유연성이 늘어날 것이다. 

 

인터페이스로 바꾸지 않더라도 테스트를 할 때 모킹(mocking) 또한 가능하다. 

이를 통해 유닛 테스트를 쉽게 작성할 수 있어 코드 품질이 향상된다. 

 

이메일 설정(EmailSettings)과 메시지(EmailMessage)를 별도의 클래스로 분리함으로써 

이메일 전송이 변경되더라도 클라이언트 코드에는 영향을 주지 않게 되었다.

→ OCP

 

각각의 클래스가 하나의 책임을 가진다.

이를 통해 유지 보수가 쉬워졌다.

→ SRP

 

EmailSender와 EmailMessage 클래스는 다른 클라이언트에서도 재사용 가능하므로 코드 중복을 줄일 수 있다.

퍼사드(Facade) 패턴 정리

복잡한 서브 시스템 의존성을 최소화하는 방법

 

장점

서브 시스템에 대한 의존성을 한곳으로 모을 수 있다.

 

단점

퍼사드 클래스가 서브 시스템에 대한 모든 의존성을 가지게 된다.

참고자료

백기선님 디자인 패턴 강의

 

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

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

www.inflearn.com