1. 문제 정의
연세대학교 골프동아리는 지원자의 합격 결과를 이메일로 공지하고 있습니다.
그런데 기존 API는 합격, 불합격자의 api uri를 다르게 사용하고 있어서 불필요한 코드의 중복이 발생하였습니다.
@PostMapping("/admin/forms/documentPassEmail")
public ResponseEntity<CustomResponse> sendDocumentPassEmail() {
applicationService.sendDocumentPassEmail();
return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 서류 합격자 이메일 전송 성공"
));
}
@PostMapping("/admin/forms/finalPassEmail")
public ResponseEntity<CustomResponse> sendFinalPassEmail() {
applicationService.sendFinalPassEmail();
return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 최종 합격자 이메일 전송 성공"
));
}
@PostMapping("/admin/forms/documentFailEmail")
public ResponseEntity<CustomResponse> sendDocumentFailEmail() {
applicationService.sendDocumentFailEmail();
return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 서류 불합격자 이메일 전송 성공"
));
}
@PostMapping("/admin/forms/finalFailEmail")
public ResponseEntity<CustomResponse> sendFinalFailEmail() {
applicationService.sendFinalFailEmail();
return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 최종 불합격자 이메일 전송 성공"
));
}
2. 개선 방안
기존 코드
public void sendDocumentPassEmail() {
List<Application> applications = findApplicationsByPassFail(true, null);
applications.stream()
.forEach(application -> emailService.sendEmail(application.getEmail(),
"안녕하세요. 연세대학교 골프동아리 결과 메일입니다.",
application.getName() + "님 서류 합격 축하드립니다. \n" +
"면접 일정은 추후 공지될 예정입니다. \n" +
"감사합니다."));
}
public void sendFinalPassEmail() {
List<Application> applications = findApplicationsByPassFail(true, true);
applications.stream()
.forEach(application -> emailService.sendEmail(application.getEmail(),
"안녕하세요. 연세대학교 골프동아리 결과 메일입니다.",
application.getName() + "님 최종 합격 축하드립니다. \n" +
"추후 일정은 문자로 공지될 예정입니다. \n" +
"감사합니다."));
}
public void sendDocumentFailEmail() {
List<Application> applications = findApplicationsByPassFail(false, null);
applications.stream()
.forEach(application -> emailService.sendEmail(application.getEmail(),
"안녕하세요. 연세대학교 골프동아리 결과 메일입니다.",
application.getName() + "님 연세골프에 지원해주셔서 감사합니다. \n\n\n" +
"안타깝게도 " + application.getName() + "님께 이번 연골 모집에서 합격의 소식을 전해드리지 못하게 되었습니다." +
application.getName() + "님의 뛰어난 열정에도 불구하고, 연세골프는 한정된 인원으로만 운영되는 만큼 아쉽게도 이런 소식을 전해드리게 됐습니다." +
"비록 이번 모집에서 " + application.getName() + "님과 함께하지 못하지만, 다음에 함께 할 수 있기를 바라겠습니다. \n\n" +
"바쁘신 와중에 지원해주셔서 감사합니다. \n\n" +
"연세 골프 운영진 드림")
);
}
public void sendFinalFailEmail() {
List<Application> applications = findApplicationsByPassFail(true, false);
applications.stream()
.forEach(application -> emailService.sendEmail(application.getEmail(),
"안녕하세요. 연세대학교 골프동아리 결과 메일입니다.",
application.getName() + "님 연세골프에 지원해주셔서 감사합니다. \n\n\n" +
"안타깝게도 " + application.getName() + "님께 이번 연골 모집에서 합격의 소식을 전해드리지 못하게 되었습니다." +
application.getName() + "님의 뛰어난 열정에도 불구하고, 연세골프는 한정된 인원으로만 운영되는 만큼 아쉽게도 이런 소식을 전해드리게 됐습니다." +
"비록 이번 모집에서 " + application.getName() + "님과 함께하지 못하지만, 다음에 함께 할 수 있기를 바라겠습니다. \n\n" +
"바쁘신 와중에 지원해주셔서 감사합니다. \n\n" +
"연세 골프 운영진 드림")
);
}
합격 결과를 분석해보면
서류 합격 : documentPass : true, finalPass : null
최종 합격 : documentPass : true, finalPass : true
면접 탈락 : documentPass : false, finalPass : null
최종 탈락 : docuemtnPass : false, finalPass : false
위와 같이 분포된 것을 알 수 있습니다.
탈락 메일의 경우 메일 양식이 같이 때문에 분기점은 3개로 나눌 수 있는 것을 알 수 있습니다.
if (isDocumentPass && isFinalPass == null) {
return 서류 합격
}
if (isDocumentPass && isFinalPass == true) {
return 최종 합격
}
return 서류 or 최종 불합격
따라서 코드를 다음과 같이 개선할 수 있습니다.
public void sendEmailNotification(boolean isDocumentPass, Boolean isFinalPass) {
final NotificationType type = getNotificationType(isDocumentPass, isFinalPass);
final String subject = "안녕하세요. 연세대학교 골프동아리 결과 메일입니다.";
findApplicationsByPassFail(isDocumentPass, isFinalPass)
.stream()
.forEach(application -> {
final String message = type.generateMessage(application.getName());
emailService.sendEmail(application.getEmail(), subject, message);
});
}
private NotificationType getNotificationType(boolean isDocumentPass, Boolean isFinalPass) {
if (isDocumentPass && isFinalPass == null) {
return NotificationType.DOCUMENT_PASS;
}
if (isDocumentPass && isFinalPass == true) {
return NotificationType.FINAL_PASS;
}
return NotificationType.FAIL;
}
package yonseigolf.server.email.dto;
public enum NotificationType {
DOCUMENT_PASS {
@Override
public String generateMessage(String name) {
return name + "님 서류 합격 축하드립니다. \n면접 일정은 추후 공지될 예정입니다. \n감사합니다.";
}
},
FINAL_PASS {
@Override
public String generateMessage(String name) {
return name + "님 최종 합격 축하드립니다. \n추후 일정은 문자로 공지될 예정입니다. \n감사합니다.";
}
},
FAIL {
@Override
public String generateMessage(String name) {
return name + "님 연세골프에 지원해주셔서 감사합니다. \n\n\n" +
"안타깝게도 " + name + "님께 이번 연골 모집에서 합격의 소식을 전해드리지 못하게 되었습니다." +
name + "님의 뛰어난 열정에도 불구하고, 연세골프는 한정된 인원으로만 운영되는 만큼 아쉽게도 이런 소식을 전해드리게 됐습니다." +
"비록 이번 모집에서 " + name + "님과 함께하지 못하지만, 다음에 함께 할 수 있기를 바라겠습니다. \n\n" +
"바쁘신 와중에 지원해주셔서 감사합니다. \n\n" +
"연세 골프 운영진 드림";
}
},
CLUB_RECRUITMENT{
@Override
public String generateMessage(String name) {
return "연세대학교 골프동아리입니다. \n" +
"연세대학교 골프동아리 모집이 시작되었습니다.\n " +
"https://yonseigolf.site/apply 에서 확인해주세요";
}
};
public abstract String generateMessage(String name);
public static NotificationType decideNotificationType(boolean isDocumentPass, Boolean isFinalPass) {
if (isDocumentPass && isFinalPass == null) {
return DOCUMENT_PASS;
}
if (isDocumentPass && isFinalPass) {
return FINAL_PASS;
}
return FAIL;
}
}
위와 같이 NotificationType으로 메시지 본문을 분리하고,
합격 불합격에 따른 분기로 나누어주면 코드의 가독성이 좋아진 것을 알 수 있습니다.
@PostMapping("/admin/forms/results")
public ResponseEntity<CustomResponse> sendEmailNotification(@RequestBody ResultNotification request) {
applicationService.sendEmailNotification(request.isDocumentPass(), request.getFinalPass());
return ResponseEntity
.ok()
.body(new CustomResponse(
"success",
200,
"연세골프 지원서 결과 이메일 전송 성공"
));
}
따라서 기존 합격 불합격에 따른 4개의 api uri로 요청을 보내는 것이 아닌, 하나의 api에 request body만 수정해서 코드의 재사용성을 높일 수 있었습니다.
3. 마무리
기존 개발을 진행할 당시, 개발 속도에만 신경쓰며 클린 코드를 지키지 못한 모습이 부끄럽게 느껴집니다. 개발 속도도 중요하지만, 추후에 다른 부원이 동아리 사이트 유지보수를 진행하게 된다면 같이 진행할 수 있도록 클린코드에 신경쓰며 개발을 진행하겠습니다.
'Yonsei Golf' 카테고리의 다른 글
모니터링 with Docker (0) | 2023.12.09 |
---|---|
JWT Token + Refresh Token (1) | 2023.11.27 |
CloudFront, S3 배포 자동화 (2) | 2023.11.26 |
Alert 개선기 (0) | 2023.11.18 |
CloudFront , S3 , Route 53 을 통한 Vue 프로젝트 배포 (0) | 2023.10.24 |