스프링과 JPA 기반 웹 애플리케이션 개발 #51 EmailService 추상화
해당 내용은 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발의 강의 내용을 바탕으로 작성된 내용입니다.

강의를 학습하며 요약한 내용을 출처를 표기하고 블로깅 또는 문서로 공개하는 것을 허용합니다 라는 원칙 하에 요약 내용을 공개합니다. 출처는 위에 언급되어있듯, 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발입니다.
제가 학습한 소스코드는 https://github.com/n00nietzsche/jakestudy_webapp 에 지속적으로 업로드 됩니다. 매 커밋 메세지에 강의의 어디 부분까지 진행됐는지 기록해놓겠습니다.
MimeMessage 전송MimeMessageHelper: MimeMessage 만들 때 사용할 수 있는 유틸리티EmailService 인터페이스void sendEmail(EmailMessage emailMessage);EmailService 인터페이스 구현체ConsoleEmailService: 콘솔 출력HtmlEmailService: JavaMailSender를 사용해서 HTML로 메일 전송기존 JavaMailSender 객체는 MimeMessage와 SimpleMailMessage를 받아서 상황(profile)에 따라 콘솔에서만 출력하거나 실제 메일을 보내거나 하는 기능을 하는 메소드가 없다.
그래서 MimeMessage와 SimpleMailMessage에서 우리가 이용하는 공통 속성들인 문자열 to, subject, text만 빼서 EmailMessage라는 것으로 추상화하고, EmailService라는 클래스를 만들어 profile이 local인지 dev인지 확인 후에 실제로 메일을 보내거나 혹은 콘솔에만 출력하는 메소드를 만들 것이다.
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmailMessage {
private String to;
private String subject;
private String text;
}
public interface EmailService {
void sendEmail(EmailMessage emailMessage);
}
@Slf4j
@Profile("local")
@Component
public class ConsoleEmailService implements EmailService{
@Override
public void sendEmail(EmailMessage emailMessage) {
log.info("sent email: {}", emailMessage.getText());
}
}
EmailService를 상속한 클래스이다. profile이 local이면 위의 클래스의 빈이 스프링 컨테이너에 올라간다. 실제로 메일을 보내진 않고 출력만 도와준다.
@Slf4j
@Profile("dev")
@Component
@RequiredArgsConstructor
public class HtmlEmailService implements EmailService{
private final JavaMailSender javaMailSender;
@Override
public void sendEmail(EmailMessage emailMessage) {
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");
mimeMessageHelper.setTo(emailMessage.getTo());
mimeMessageHelper.setSubject(emailMessage.getSubject());
mimeMessageHelper.setText(emailMessage.getText(), false);
javaMailSender.send(mimeMessage);
log.info("sent email: {}", emailMessage.getText());
} catch (MessagingException e) {
e.printStackTrace();
log.error("failed to send email", e);
}
}
}
동일하게 EmailService를 상속한 클래스이다. profile이 dev인 경우에 위의 클래스가 스프링 컨테이너에 빈으로 올라간다. ConsoleEmailService와 HtmlEmailService는 다형성을 통해 상위 타입(EmailService)의 빈의 같은 멤버에 주입될 수 있다.
그래서 AccountService의 내용을 다음과 같이 만들면, ConsoleEmailservice와 HtmlEmailService를 profile에 따라 코드는 변경하지 않고 이용할 수 있다.
...
EmailMessage emailMessage = new EmailMessage(
account.getEmail(),
"회원가입 인증",
"/check-email-token?token=" + account.getEmailCheckToken() + "&email=" + account.getEmail()
);
emailService.sendEmail(emailMessage);
...