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

icebox127·2026년 1월 13일

TO:DAY 서버

목록 보기
1/8

이메일로 회원가입하는 경우 해당 이메일에 인증번호를 보내 본인의 이메일이 맞는지 확인하는 과정을 거치게 된다. 프로젝트를 진행하며, 이메일 인증 구현한 내용을 정리해보았다.

구현 과정

1. 구글 계정 준비

나는 프로젝트 용으로 새 구글 계정을 하나 만들었다.
구글 계정에서 2단계 보안 설정을 한 후, 앱 비밀번호를 발급받는다.

앱 비밀번호를 사용하면 최신 보안 표준을 지원하지 않는 오래된 앱 및 서비스에서 Google 계정에 로그인할 수 있습니다.

-> 스프링에서 해당 이메일에 접근하여 인증코드를 보내야하기 때문에! 꼭 필요하다

저 화면에서 만들기를 누르면 팝업창에 16자리의 앱 비밀번호가 나오는데, 이걸 따로 복사해둔 후 사용한다.

2. 이메일 설정


POP, IMAP 사용을 하도록 다음과 같이 설정한다.
(다른 블로그는 <IMAP 사용하기> 항목도 선택해야하던데 나는 뜨지 않았다.
하지만 IMAP 액세스를 설정하는 것 자체가 IMAP를 사용가능한거 같다.)

3. 파일 설정

build.gradle 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-mail'

application.yaml 추가

spring:
  mail:
    host: smtp.gmail.com
    port: 587
    username: ${mail.username}
    password: ${mail.password}
    properties:
      mail:
        smtp:
          auth: true
          timeout: 5000
          starttls:
            enable: true
  • host: STMP 서버 호스트
  • port: Gmail SMTP 서버 표준 포트 번호
  • username: 내 메일 이름 (예: umc9today@gmail.com)
  • password: 1단계에서 발급받은 앱 비밀번호 16자리
  • auth: 사용자 인증시도 여부 (SMTP 서버에 로그인하고 메일을 보내는걸 허용)
  • timeout: STMP 서버로부터의 응답 대기 시간 (설정하지 않으면 무한대지만, 메일 서버가 응답을 안 해도 계속 대기해서 성능에 약영향이 생길 수 있음)

4. 서비스 코드 작성

import com.example.todayserver.domain.member.excpetion.AuthException;
import com.example.todayserver.domain.member.excpetion.code.AuthErrorCode;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring6.SpringTemplateEngine;

import java.util.Random;

@Service
@RequiredArgsConstructor
public class EmailService {

    private final JavaMailSender javaMailSender;
    private final SpringTemplateEngine templateEngine;

    @Value("${spring.mail.username}")
    private String fromEmail;

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

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

            return code;
        } catch (MessagingException e) {
            throw new AuthException(AuthErrorCode.CODE_ERROR);
        }
    }

    // 인증번호 생성
    private String generateVerificationCode() {
        return String.valueOf(100000 + new Random().nextInt(900000));
    }

    // 인증 이메일 뷰 생성
    private String createHtmlEmailBody(String code) {
        Context context = new Context();
        context.setVariable("code", code);
        return templateEngine.process("email_code", context);
    }
}
  • setTO: 수신자 이메일 설정

  • setSubject: 메일 제목

  • setText: 메일 본문 (2번째 파라미터는 html로 보낼건지 여부 -> true로 표시)

  • setFrom: 발신자 이메일 설정 (앞서 환경변수 선언해둔 값을 사용)

  • Context: 뷰에 전달할 데이터 담음 (인증코드 주입)

  • return templateEngine.process("email_code", context); : 여기서 "email_code" = html 파일 이름이다.

5. HTML 작성

build.gradle 의존성 추가

//thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

https://jsfiddle.net/
해당 사이트에 가면 HTML 코드의 실행화면을 보여줘서 수정하기 좋다.

html 코드는 resource/templates 하위에 생성했다.

<table width="100%" cellpadding="0" cellspacing="0">
    <tr>
        <td align="center">
            <table width="600" cellpadding="0" cellspacing="0"
                   style="background-color:#ffffff; margin:40px 0; padding:40px;
                          border-radius:8px; font-family:Arial, sans-serif;
                          box-shadow:0 4px 10px rgba(0,0,0,0.08);">

                <tr>
                    <td align="center">
                        <h1 style="margin:0; color:#333;">안녕하세요 👋</h1>
                        <p style="margin-top:10px; font-size:16px; color:#555;">
                            올인원 할일 관리 서비스 <strong>TO:DAY</strong>입니다.
                        </p>
                    </td>
                </tr>

                <tr>
                    <td style="padding:30px 0; text-align:center;">
                        <p style="font-size:15px; color:#666;">
                            서비스로 돌아가 아래 <strong>인증 코드</strong>를 입력해주세요.
                        </p>
                    </td>
                </tr>

                <tr>
                    <td align="center">
                        <div style="border:1px solid #e0e0e0;
                                    border-radius:6px;
                                    padding:25px;
                                    width:100%;
                                    box-sizing:border-box;">
                            <p style="margin:0; font-size:14px; color:#888;">
                                회원가입 인증 코드
                            </p>
                            <p style="margin-top:15px;
                                      font-size:28px;
                                      letter-spacing:6px;
                                      font-weight:bold;
                                      color:#2f80ed;"
                               th:text="${code}">
                                123456
                            </p>
                        </div>
                    </td>
                </tr>

                <tr>
                    <td style="padding-top:30px; text-align:center;">
                        <p style="font-size:13px; color:#999;">
                            본 메일은 인증 요청에 의해 자동 발송되었습니다.<br>
                            인증을 요청하지 않으셨다면 이 메일을 무시해주세요.
                        </p>
                    </td>
                </tr>

            </table>
        </td>
    </tr>
</table>

실행 결과

profile
감자의 공부기록🥔

0개의 댓글