기술과 산업/언어 및 프레임워크
Spring Boot 시리즈 11편 – 이메일 인증 및 비밀번호 재설정: 실전 보안 흐름 구현 전략
B컷개발자
2025. 4. 25. 16:30
728x90
Spring Boot에서 이메일 인증과 비밀번호 재설정 흐름을 안전하게 구현하는 방법을 소개합니다. 인증 토큰 발급, 만료 처리, 보안 설계 전략까지 포함된 실전 가이드입니다.
Spring Boot 시리즈 11편 – 이메일 인증 및 비밀번호 재설정: 실전 보안 흐름 구현 전략
대부분의 서비스에서 이메일 인증은 신뢰 기반 사용자 확보를 위해,
비밀번호 재설정은 보안 사고 예방을 위해 반드시 필요한 기능입니다.
이번 글에서는 Spring Boot 기반으로 이메일 인증 및 비밀번호 재설정 기능을 보안성, 유지보수성, 사용자 경험까지 고려하여
기획부터 구현까지 실무 수준으로 구성해보겠습니다.
📌 1. 이메일 인증이 필요한 이유
목적 설명
가입 계정 유효성 검증 | 실사용자 확인 (가짜/스팸 방지) |
계정 활성화 조건 설정 | 이메일 인증 전 로그인 차단 가능 |
비밀번호 재설정 시 본인 확인 | 이메일을 통해 본인만 접근 가능하도록 설정 |
보안 사고 대응 | 인증 링크는 1회성 & 시간 제한으로 제한 필요 |
🔄 2. 이메일 인증 흐름 설계
[1] 회원가입 요청 → 이메일 발송
[2] 사용자 메일함 → 인증 링크 클릭
[3] 백엔드에서 토큰 검증 → 계정 활성화 처리
✅ 3. 인증 토큰 Entity 설계
@Entity
public class VerificationToken {
@Id
@GeneratedValue
private Long id;
private String token;
private String userEmail;
private LocalDateTime expiryDate;
public static VerificationToken generate(String email) {
return new VerificationToken(UUID.randomUUID().toString(), email, LocalDateTime.now().plusHours(1));
}
public boolean isExpired() {
return LocalDateTime.now().isAfter(expiryDate);
}
}
✉️ 4. 이메일 발송 서비스
1️⃣ 토큰 생성 + 이메일 전송
@Service
@RequiredArgsConstructor
public class EmailVerificationService {
private final VerificationTokenRepository tokenRepository;
private final EmailSender emailSender;
public void sendVerificationEmail(String email) {
VerificationToken token = VerificationToken.generate(email);
tokenRepository.save(token);
String link = "https://myapp.com/api/auth/verify?token=" + token.getToken();
String body = "이메일 인증을 완료하려면 아래 링크를 클릭하세요.\n" + link;
emailSender.send(email, "회원가입 이메일 인증", body);
}
}
2️⃣ 인증 완료 처리
public void verifyToken(String token) {
VerificationToken vt = tokenRepository.findByToken(token)
.orElseThrow(() -> new BusinessException(ErrorCode.INVALID_TOKEN));
if (vt.isExpired()) {
throw new BusinessException(ErrorCode.EXPIRED_TOKEN);
}
User user = userRepository.findByEmail(vt.getUserEmail())
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));
user.activate(); // 계정 활성화
userRepository.save(user);
tokenRepository.delete(vt); // 1회성 토큰 폐기
}
🔐 5. 비밀번호 재설정 흐름 설계
[1] 사용자 이메일 입력 → 임시 토큰 생성 및 메일 발송
[2] 메일의 링크 클릭 → 새로운 비밀번호 입력 폼
[3] 토큰 검증 → 비밀번호 변경 처리
🧱 6. 비밀번호 재설정 토큰 구조 (재사용 가능)
@Entity
public class PasswordResetToken {
@Id @GeneratedValue
private Long id;
private String token;
private String email;
private LocalDateTime expiresAt;
public static PasswordResetToken create(String email) {
return new PasswordResetToken(UUID.randomUUID().toString(), email, LocalDateTime.now().plusMinutes(30));
}
public boolean isExpired() {
return LocalDateTime.now().isAfter(expiresAt);
}
}
🔁 7. 재설정 API 흐름 예시
1️⃣ 메일 발송 API
@PostMapping("/api/auth/reset-password-request")
public ApiResponse<Void> requestPasswordReset(@RequestBody EmailRequest request) {
passwordResetService.sendResetLink(request.getEmail());
return ApiResponse.success();
}
2️⃣ 비밀번호 변경 API
@PostMapping("/api/auth/reset-password")
public ApiResponse<Void> resetPassword(@RequestBody ResetPasswordRequest request) {
passwordResetService.resetPassword(request.getToken(), request.getNewPassword());
return ApiResponse.success();
}
🧠 보안 고려 사항
항목 권장 설계
토큰 만료시간 | 30분 ~ 1시간 이내 제한 |
링크 유효성 | 단일 사용 후 삭제 or 만료 |
사용자 피드백 | "링크가 만료되었습니다" 등의 UX 메시지 중요 |
토큰 식별자 | UUID + 이메일 등 혼합 전략 사용 가능 |
이메일 전송 | 비밀번호는 절대 메일에 포함하지 말 것 |
✅ 마무리 요약
항목 요약
인증 흐름 | 이메일 → 링크 클릭 → 토큰 검증 → 계정 활성화 |
토큰 설계 | VerificationToken, PasswordResetToken 등 Entity 기반 관리 |
메일 발송 | 이메일 전송은 비동기 or 별도 서비스로 분리 권장 |
보안 설계 | 만료 시간, 1회성 제한, 예외 처리 통일 |
UX 강화 | 사용자에게 명확한 안내 메시지와 흐름 제공 |
📌 다음 편 예고
Spring Boot 시리즈 12편: 파일 업로드 처리 전략 – 이미지, 문서 업로드부터 S3 연동까지 실전 가이드
728x90