메일을 보내는 메소드가 존재.

해당 메소드는 매일 메일을 받기로 한 모든 유저에게 메일을 보내야 하는 상황이었다.

        userUrlMap.forEach((userInterest, url) -> {
            try {
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

                helper.setTo(userInterest.getReceiveEmail());
                String title = "title";
                helper.setSubject(title);
                String htmlContent = getMailHTML(url);
                helper.setText(htmlContent, true);
                helper.setFrom(fromEmail, fromName);

                javaMailSender.send(message);
            } catch (Exception e) {
                log.info(e.getMessage());
            } finally {
                userInterest.setIsTodaySendMail(true);
                userInterestRepository.saveAndFlush(userInterest);
            }
        });

메일은 JavaMailSender 를 사용해서 전송 중이었으며, 인원 한 명에게 보내는데 대략 0.5초 가량이 걸리고 있었다.

문제는 메일을 보내야 하는 인원이 증가함에 따라, 전송 시간이 길어졌고, 어느 순간 배포를 진행했다가 배포로 인해 서버가 다운, 메일 전송 메소드가 중도에 끊겨 버리는 이슈가 발생했다.

생각한 해결 방법은 먼저

  1. 별도 메일 서버를 분리, 해당 메일 서버에서 메일을 전송하는 것이다.
    1. 가장 간편하나, 서버 증설은 비용 문제로 인해서 불가능하다. 따라서 제외
  2. 위 코드에서는 한 번에 모든 유저에게 메일을 전송 중 인데 이를 각각 유저에게 전송하는 방식으로 변경 후, 스케쥴링을 통해 매 분마다 호출. 해당 메소드 자체 호출 횟수를 늘린다.
    1. 이 방법으로 진행하여 전송 시 유저에게 당일 전송을 판별하는 status 값을 저장.
      1. 메일의 종류가 늘어날 수록 해당 status 값의 종류도 늘어나야 함.
    2. 시간 단위로 호출? → 호출이 되지 않는 시간대에 낭비
  3. 메세지 큐 도입. 큐에 보낼 메일 작업들을 보내 놓고, 이를 컨슘하는 방식으로 메일을 전송한다.
    1. 배포 시 code deploy에서 새로운 asg를 생성하기 때문에 기존 인스턴스 내에 추가하는 방식은 불가능.
    2. 그렇다면 별도 큐 서버가 추가가 되어야 한다는 것인데, 이는 1에서 언급한 것과 마찬가지로 비용 문제로 인한 불가.

그래서 결론적으로는 2번을 선택하기로 했다. 3번이 가장 깔끔해 보이기는 하나, 비용 상의 문제로 2번을 선택하고, 추후 비용 문제가 어느 정도 해결되었을 때, 3번으로 변경하기로 한다.