회원가입시 이메일 인증을 구현해놓았다. >이전 포스팅: '회원가입시 이메일인증 구현하기'
그런데 서비스를 운영하며 받은 사용자 피드백(구글 설문조사)에서 이것에 대한 불편사항이 접수되었다.
인증 메일 발송 처리가 완료되면 시스템 alert로 "인증번호를 입력해주세요."가 출력되도록 코드를 짜놓았다. 하지만 이메일 발송이 완료되는데까지 시간이 오래 걸리기니 사용자가 이것을 즉각적으로 확인 할 수 없었던 것이다. (약 4초 소요)
코드 자체가 문제인 상황은 아니었다. 에러가 발생한다면 alert로 무엇이 잘못되었는지 등이 제대로 출력되기 때문이다. 문제는 반응성.
사용자 입장에서 "내가 뭔가 잘못 입력한건가?", "이제 이메일 인증을 하면 되는가?" 등을 판단 할 수 있도록 즉각적으로 확인 할 수 있어야한다.
따라서 코드의 변경을 최소화하여 기존의 잘못된 입력을 캐치하는 기능을 유지하면서도,
반응성을 개선 할 수 있는 비동기적 프로그래밍을 계획하였다.
코드 변경 최소화와 더불어, 트래픽이 과도하게 발생할 것이라고 생각하지 않았다.
따라서 WebFlux
보다는@Async
로 특정 함수만 비동기적으로 처리하는 방향으로 결정했다.
Controller에서 처리가 오래걸리는 부분은 signup
메서드이다.
하지만 아래와 같이 Service 메서드 전체를 비동기적으로 처리한다면,
입력값이 잘못되었을 때 에러 처리가 힘들다는 문제가 있었다.
@PostMapping("/auth/signup")
public ResponseEntity<ApiResponse> signupAsync(
@Valid @RequestBody SignupRequestDto signupRequestDto,
HttpServletResponse response){
String loginId = signupRequestDto.getLoginId();
//쿠키를클라이언트에먼저추가
userService.signup(signupRequestDto);
Cookiecookie = emailAuthService.getCookieByLoginId(loginId);
response.addCookie(cookie);
//클라이언트에먼저응답보내기
return ResponseEntity.ok(newApiResponse<>("인증번호를입력해주세요.",HttpStatus.OK.value()));
}
@Async // Service 메서드 전체를 비동기처리한다면 입력값에 대한 에러 처리를 하지 못함
public void signup(SignupRequestDto signupRequestDto){
...
}
이 문제를 해결하기 위해 singup
이라는 서비스메서드 전체를 비동기 처리하는 것이 아니라, 특정 메서드들만 비동기 처리하는 방법을 사용했다.
특정 메서드는 "입력값에 대한 확인이 끝난 후 실행시키지만 처리가 오래 걸리는 메서드"로 결정했다.
따라서 '이메일을 발송하는 함수'와 'Redis에 정보를 저장하는 함수'의 return값을 void
로 변경하고 비동기적으로 처리해주었다.
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender javaMailSender;
@Async
public void sendEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
javaMailSender.send(message);
}
@Async
public void setSentCodeByLoginIdAtRedis(String loginId, String nickname, String email,
String password, Long firstPreferredCategoryId, Long secondPreferredCategoryId,
String sentCode) {
...(redis에 인증정보 저장)
}
코드 개선 후 4.07 s 에서 0.095 s 로, 비교도 할 수 없을 정도로 반응속도가 빨라졌다!
사용자 피드백 덕분에 더 좋은 코드를 고민하여 개선 할 수 있었다.
(속도 테스트는 로컬에서 진행)