남·여 매칭 서비스 개발 중 학교 인증 기능을 위해 이메일 인증 기능을 도입하게 되었다.
기능은 완성하였으나 유지보수·확장 면에서 부족한 부분이 있어 리팩토링을 하게 되었다.
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender javaMailSender;
public void sendEmail(String toEmail) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
String verificationCode = createVerificationCode();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
mimeMessageHelper.setSubject("MakeLover 인증코드 메일 💌");
mimeMessageHelper.setFrom("makeloverwithus@naver.com");
mimeMessageHelper.setTo(toEmail);
String content = "<h2>MakeLover 인증코드입니다 <br> 서비스에 돌아가서 입력해 주세요</h2>\n"
+ "<h3>인증코드 : " + verificationCode + "</h3>"
+ "<img src=\"cid:love-image\" alt=\"대체 텍스트\">";
mimeMessageHelper.setText(content, true);
mimeMessageHelper.addInline("love-image", new ClassPathResource("static/love.png"));
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
private String createVerificationCode() {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
}
기존 코드에는 다음과 같은 문제점들이 존재했다
- HTML base 의 이메일 content 에서 Java 코드와 HTML 이 뒤섞여있어 유지보수가 어렵다
- 이메일을 보내는 작업이 여러 번 필요하다고 한다면 중복된 코드가 여러 번 발생하게 된다
- 한 메서드에서 메일을 보내는 기능과 메일을 만드는 기능이 모두 있다
따라서 다음과 같은 리팩토링이 필요하였다
- view 화면과 데이터의 분리
- 함수가 1가지만 하도록 함수 나누기
또한 클린코드에서 말하듯이 함수 당 추상화 수준을 동일하게 하였다. (등록을 위한 이메일 발송 기능에서 이메일 만들기, 이메일 발송과 같은 동일한 추상화 수준을 사용하였다)
또한 내려가기 규칙을 활용하여 아래로 내려갈 수록 추상화 수준이 낮아지도록 하였다.
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender javaMailSender;
private final SpringTemplateEngine springTemplateEngine;
/*
동일한 추상화 수준으로 refactoring
1. 이메일을 만드는 기능
2. 이메일 발송 기능
함수를 잘게 나눈 결과 이메일을 보내는 작업이 또 생기더라도 이메일을 만드는 메서드 하나만 추가하면 된다.
핵심으로는 중복이 사라진다.
*/
public void sendEmailForRegister(String toEmail) {
MimeMessage mimeMessage = makeEmailForRegister(toEmail);
sendEmail(mimeMessage);
}
private MimeMessage makeEmailForRegister(String toEmail) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
String verificationCode = createVerificationCode();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
mimeMessageHelper.setSubject("MakeLover 인증코드 메일 💌");
mimeMessageHelper.setFrom("makeloverwithus@naver.com");
mimeMessageHelper.setTo(toEmail);
Context context = new Context();
context.setVariable("code", verificationCode);
String emailContent = springTemplateEngine.process("mail.html", context);
mimeMessageHelper.setText(emailContent, true);
mimeMessageHelper.addInline("love-image", new ClassPathResource("static/love.png"));
} catch (MessagingException e) {
throw new EmailCreationFailedException(ErrorCode.EMAIL_CREATION_FAILED);
}
return mimeMessage;
}
private void sendEmail(MimeMessage mimeMessage) {
try {
javaMailSender.send(mimeMessage);
} catch (MailException e) {
throw new EmailSendFailedException(ErrorCode.EMAIL_SEND_FAILED);
}
}
private String createVerificationCode() {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
}
다음은 static 폴더 밑에 있는 mail.html
# mail.html
<!DOCTYPE html>
<html lang="ko">
<body>
<h2>학교별 남·여 매칭서비스 플랫폼 MakeLover 입니다 </h2>
<h2>인증코드를 알려드리오니 서비스에 돌아가서 입력해 주세요</h2>
<h2>인증 코드 : <span th:text="${code}"></span></h2>
<img src="cid:love-image" alt="대체 이미지"/>
</body>
</html>
결과
'개인 프로젝트 > 남·여 매칭 서비스' 카테고리의 다른 글
이메일 인증 처리에 대한 여러가지 방법 (0) | 2023.09.12 |
---|