1. Redis 사용 중지
LoaTodo는 현재(2024년 2월 1일) 이메일로 가입하는 방식과 구글과 연동해서 가입하는 방식
두가지를 지원하고 있습니다.
그 중 인증번호를 확인하는 로직에서
데이터를 저장하는 용도로 Redis를 사용하고 있고
Redis 서버는 AWS ElastiCache에서 구축하고 있습니다.
[ 코드 일부 ]
public int sendMail(String mail){
MimeMessage message = createMail(mail);
javaMailSender.send(message);
saveRedis(mail, number);
return number;
}
public boolean checkMail(MailCheckDto mailCheckDto) {
List<Mail> allByMail = repository.findAllByMail(mailCheckDto.getMail());
if (!allByMail.isEmpty()) {
for (Mail mail : allByMail) {
if (mail.getNumber() == mailCheckDto.getNumber()
&& Duration.between(mail.getRegDate(), LocalDateTime.now()).toMinutes() <= 3) {
mail.setCheck(true);
repository.save(mail);
return true;
}
}
}
return false;
}
- sendMail 메소드는 인증번호를 전송하면서 동시에 Redis에 보낸 메일과 인증번호를 저장합니다.
- checkMail 메소드는 사용자가 입력한 인증번호와 Redis에 저장된 인증번호가 일치하는지 확인 후
일치하면 저장된 데이터의 check(boolean) 값을 변경합니다.- check(boolean) 값은 회원가입 로직이 실행될때 또한 확인되어 이중으로 이메일 인증이 확인됩니다.
또한 Redis에 자주 읽는 데이터를 저장하여 필요할 때 빠르게 읽을 수 있는 장점이 있어
프로젝트에서 유용하게 사용할 수 있지만...
비쌉니다....
37.8달러면 현재 시세로 약 5만원 정도....
가난한 개발자가 감당하기 힘든 금액으로 Redis 사용을 중지하려고 합니다.
그럼 이메일 인증에서
인증번호를 저장하는 저장소를 다른 곳에 구현해야하는데 두가지 방식이 있습니다.
- 백엔드 서버(Spring boot) 메모리에 저장
- 관계형 데이터베이스(MySQL)에 저장
2. 백엔드 서버 메모리에 저장
간단히 HashMap 혹은 ConcurrentHashMap을 이용해서 메모리에 저장해놓는 방식입니다.
하지만 이러한 방식은 단점이 많습니다.
- 메모리에 저장하는 것이므로, 서버의 메모리 한계에 도달할 수 있습니다
- 서버가 재시작되거나 오류가 생기면 모든 데이터가 손실될 수 있습니다
- 로드밸런서를 사용하여 서버가 여러개가 분리되면 데이터 불일치가 발생할 수 있습니다.
- 스레드의 불안정으로 인하여 여러 클라이언트가 동시에 HashMap을 수정하려는 경우 데이터 손상이 발생할 수 있습니다
- 메모리 내에 데이터를 저장하기 때문에 보안에 취약합니다
AWS EC2로 사용하고 있는 서버의 메모리가 부족한 관계로 이 방식은 사용하지 않았습니다.
3. 관계형 데이터베이스에 저장
Redis에 저장하던 데이터를 그대로 RDBMS에 저장하는 방식입니다.
읽고 쓰는 속도면에서는 다소 차이가 날 수 있으나
컬럼이 많이 없고, 구글로그인 대비 하루에 가입하는 가입자 수가 적어 차이가 미미할 것입니다.
SELECT
DATE(created_date),
COUNT(CASE WHEN auth_provider = 'none' THEN 1 END) AS 이메일_인증_가입자,
COUNT(CASE WHEN auth_provider = 'google' THEN 1 END) AS 구글_로그인_가입자
FROM
member
GROUP BY
DATE(created_date);