[Spring] 이메일 인증 코드 확인 구현

icebox127·2026년 1월 14일

TO:DAY 서버

목록 보기
2/8

지난 포스트 - 이메일 인증 코드 발송
https://velog.io/@icebox127/Spring-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EC%BD%94%EB%93%9C-%EB%B0%9C%EC%86%A1-%EA%B5%AC%ED%98%84

이메일 코드를 발송한 후, 어떻게 관리하는지에 대해 정리해보았다.
지난 번에는 랜덤 코드를 이메일로 보내는 것까지만 구현했는데, 여기에 이 이메일과 랜덤 코드를 저장하는 기능을 추가한다. 추후 사용자가 인증번호 확인 요청을 할 때 이를 대조하여야하기 때문이다.

구현 과정

1. 엔터티 생성

EmailVerification.java

@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "email_verification")
public class EmailVerification {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email", nullable = false)
    private String email;

    @Column(name = "code", nullable = false)
    private String code;

    @Column(name = "expire_date", nullable = false)
    private LocalDateTime expireDate;

    @Column(name = "verfied", nullable = false)
    private boolean verified = false;

    public void verify() {
        this.verified = true;
    }

    public boolean isExpired() {
        return LocalDateTime.now().isAfter(expireDate);
    }
}

아이디, 사용자 이메일, 코드, 만기일시, 검증여부를 저장한다.

  • @GeneratedValue(strategy = GenerationType.IDENTITY) -> AUTOINCREMENT 설정
  • verify(): 검증 성공 시 true로 변환
  • isExpired(): 현재 시간이 만기시간보다 이후이면 만료되었다고 true 반환

2. 리포지토리 추가

EmailCodeRepository.java

public interface EmailCodeRepository extends JpaRepository<EmailVerification, Long> {
    Optional<EmailVerification> findByEmailAndCode(
            String email, String verificationCode);
    void deleteByEmail(String email);
}

앞서 만든 EmailVerification 엔터티를 조작할 리포지토리를 생성
이메일과 코드에 해당하는 값을 리턴할 findByEmailAndCode,
이전 값들을 지울 deleteByEmail 두 개의 메서드를 생성했다.

3. 서비스 코드 추가

public void sendVerificationEmail(String emailTo, String type) {
        String code = generateVerificationCode();
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();

        try {
            sendVerifyCode(emailTo, mimeMessage, code, type);
            saveEmailVerifyCode(emailTo, code);
        } catch (MessagingException e) {
            throw new AuthException(AuthErrorCode.CODE_ERROR);
        }
    }

    private void sendVerifyCode(String emailTo, MimeMessage mimeMessage, String code, String type) throws MessagingException {
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");
        mimeMessageHelper.setTo(emailTo);
        mimeMessageHelper.setSubject("[TO:DAY] 이메일 인증 코드 발송");
        mimeMessageHelper.setText(createHtmlEmailBody(code, type),true);
        mimeMessageHelper.setFrom(fromEmail);
        javaMailSender.send(mimeMessage);
    }

    private void saveEmailVerifyCode(String emailTo, String code) {
        emailCodeRepository.deleteByEmail(emailTo);
        EmailVerification ev = EmailVerification.builder()
                .email(emailTo)
                .code(code)
                .expireDate(LocalDateTime.now().plusMinutes(10))
                .build();
        emailCodeRepository.save(ev);
    }

지난 번 코드에 saveEmailVerifyCode를 추가한다.
+) 인증코드 전송 부분도 메소드를 추출해서 try문을 짧게 만들었다.
메소드 추출 단축키: Ctrl+ Alt + M

.expireDate(LocalDateTime.now().plusMinutes(10))
만료 시간은 10분으로 설정했다. (현재시간 + 10분)

db에 저장하는거라 데이터가 너무 많이 쌓일것을 고려하여, 새로운 코드를 발급받을 경우 해당 이메일이 발급받은 이전 코드는 전부 삭제하도록 하였다.

4. 서비스 코드 구현

 public void checkEmailVerifyCode(String email, String code){
        EmailVerification ev = emailCodeRepository.findByEmailAndCode(email, code)
                .orElseThrow(() -> new AuthException(AuthErrorCode.CODE_NOT_EXIST));

        if (ev.isExpired()){
            throw new AuthException(AuthErrorCode.CODE_EXPIRED);
        }
        ev.verify();
    }

checkEmailVerifyCode를 따로 구현하였다.
만약 해당 이메일과 코드가 저장되어있지 않다면 (즉, 코드가 틀림) CODE_NOT_EXIST 에러를 발생 시킨다.
존재한다면, 만료여부를 확인하고 만료 시 CODE_EXPIRED 에러 발생시킨다.
만약 두 경우 다 아닐 시, verify = true로 인증을 성공시킨다.

실행 결과

받은 인증코드 47913으로 요청을 하니 성공적으로 처리되었다.

참고

https://devmee.tistory.com/96

profile
감자의 공부기록🥔

0개의 댓글