Skip to content

Feature/email verification - #18

Open
ryuyejun wants to merge 1 commit into
developfrom
feature/email-verification
Open

ryuyejun wants to merge 1 commit into
developfrom
feature/email-verification

Conversation

@ryuyejun

Copy link
Copy Markdown
Collaborator

🔀 Pull Request

1. 작업 내용

이메일 인증번호 발송 및 검증 기능을 구현하고, 이메일 인증을 완료한 사용자만 회원가입할 수 있도록 기존 회원가입 기능과 연동했습니다.

주요 변경 사항

  • Gmail SMTP를 이용한 이메일 인증번호 발송 및 검증 기능 구현
  • Redis 기반 인증번호 유효기간, 재발송 제한 및 인증 시도 횟수 관리
  • 일회성 이메일 인증 토큰을 활용한 회원가입 검증 기능 추가
  • Redis 장애 및 이메일 발송 실패에 대한 예외 처리 개선
  • 이메일 인증 관련 API 문서 및 자동화 테스트 추가

2. 구현 상세

구현 방식

  • 6자리 이메일 인증번호를 생성하고 HMAC-SHA256으로 처리하여 Redis에 저장합니다.
  • 인증번호 유효기간은 5분, 재발송 제한 시간은 60초로 설정했습니다.
  • 인증번호 입력 시도 횟수를 최대 5회로 제한했습니다.
  • 이메일 인증 성공 시 10분간 유효한 일회성 인증 토큰을 발급합니다.
  • 회원가입 시 이메일과 인증 토큰을 검증한 후 사용자 정보를 저장합니다.
  • Redis Lua 스크립트를 활용하여 인증번호 검증과 인증 토큰 예약을 원자적으로 처리합니다.

설계 및 기술적 결정

  • 인증번호와 인증 토큰을 평문으로 Redis에 저장하지 않도록 구현했습니다.
  • 이메일 정규화 로직을 공통화하여 로그인, 회원가입, 이메일 인증에서 동일하게 처리합니다.
  • 회원가입 시 인증 토큰을 예약하고 DB 트랜잭션 결과에 따라 토큰을 소모하거나 예약을 복구합니다.
  • SMTP 발송 실패 시 기존 인증 상태를 보존하도록 개선했습니다.
  • 동시 재발송 요청이 발생해도 이전 요청이 최신 인증 상태를 덮어쓰지 못하도록 처리했습니다.
  • Redis 예약 정리 실패 시 민감정보를 제외한 추적 정보를 로그에 기록하도록 개선했습니다.

3. API 변경 내역

Method Endpoint Description
POST /auth/email/send 이메일 인증번호 발송
POST /auth/email/verify 이메일 인증번호 검증 및 인증 토큰 발급
POST /auth/signup 회원가입 요청에 이메일 인증 토큰 필수 추가

Request / Response

이메일 인증번호 발송 요청

{
  "email": "user@example.com"
}

이메일 인증번호 검증 요청

{
  "email": "user@example.com",
  "code": "123456"
}

이메일 인증 성공 응답의 data 예시

{
  "email": "user@example.com",
  "verified": true,
  "expiresIn": 600,
  "verificationToken": "<발급된 인증 토큰>"
}

회원가입 요청 예시

{
  "email": "user@example.com",
  "password": "Password123!",
  "passwordConfirm": "Password123!",
  "nickname": "사용자",
  "verificationToken": "<발급된 인증 토큰>"
}

※ 기존 회원가입 API에 verificationToken 필드가 추가되어 이메일 인증 완료 후 회원가입할 수 있습니다.

4. 데이터 및 인프라 영향

  • Database: MySQL 테이블 및 엔티티 스키마 변경 없음
  • Configuration:
    • Redis 연결 설정 추가
    • Gmail SMTP 설정 추가
    • MAIL_USERNAME, MAIL_PASSWORD, EMAIL_VERIFICATION_SECRET 환경변수 필요
    • 로컬 JPA 설정을 ddl-auto: update에서 validate로 변경
  • Dependencies:
    • spring-boot-starter-data-redis 추가
    • spring-boot-starter-mail 추가
  • Compatibility:
    • 기존 로그인 API 유지
    • 회원가입 요청에 verificationToken 필수 추가
    • 프론트엔드에서 이메일 인증 후 발급받은 토큰을 회원가입 요청에 포함해야 함

5. 테스트 결과

테스트 항목 결과
Build 전체 테스트 실행 및 통과 보고
Unit Test 통과
Integration Test Redis 통합 테스트 23개 통과
API Test 컨트롤러 자동화 테스트 통과 (실제 Gmail 발송 미검증)

검증 내용

  • 전체 자동화 테스트 182개 통과 (실패 및 건너뜀 0개)
  • 이메일 인증번호 발송 및 검증
  • 인증번호 만료 및 입력 횟수 제한
  • 인증번호 재발송 제한 및 동시 요청 처리
  • SMTP 발송 실패 시 기존 인증 상태 보존
  • Redis 장애 및 인증 토큰 예약 정리 실패 처리
  • 회원가입 트랜잭션 커밋·롤백에 따른 인증 토큰 처리
  • 기존 회원가입·로그인·JWT 기능 회귀 테스트
  • git diff --check 통과

6. 리뷰 포인트

  • Redis Lua 스크립트를 활용한 인증번호 검증 및 토큰 예약 처리의 적절성
  • 회원가입 트랜잭션 성공·실패에 따른 인증 토큰 소모 및 복구 로직
  • 이메일 재발송 실패 및 동시 요청 발생 시 인증 상태의 일관성
  • 기존 회원가입 API에 인증 토큰을 필수로 추가한 변경 사항
  • Redis 및 Gmail SMTP 장애 발생 시 예외 처리의 적절성

7. 배포 참고 사항

  • 배포 전 확인:

    • Redis 서버 실행 및 연결 상태 확인
    • Gmail SMTP 계정 및 앱 비밀번호 설정
    • MAIL_USERNAME, MAIL_PASSWORD, EMAIL_VERIFICATION_SECRET, JWT_SECRET 환경변수 설정
    • 프론트엔드 회원가입 요청에 verificationToken 필드 반영
    • ddl-auto: validate 적용에 따른 DB 스키마 일치 여부 확인
  • 배포 후 확인:

    • 실제 이메일 인증번호 발송 및 수신 여부 확인
    • 인증번호 검증 후 회원가입 정상 처리 여부 확인
    • Redis 및 SMTP 연결 오류 로그 확인
    • 기존 로그인 및 JWT 인증 기능 정상 동작 여부 확인
  • 롤백 고려사항:

    • MySQL 스키마 변경이 없어 별도의 DB 마이그레이션 롤백은 필요하지 않음
    • 이메일 인증 기능 롤백 시 회원가입 API의 verificationToken 필수 조건도 함께 복원해야 함
    • 프론트엔드와 백엔드의 회원가입 요청 형식을 일치시켜야 함

8. 관련 이슈

해당 없음


✅ Merge Checklist

  • 요구사항에 맞게 구현했습니다.
  • 예외 처리 및 입력값 검증을 확인했습니다.
  • 기존 기능에 미치는 영향을 검토했습니다.
  • 인증·인가 및 민감정보 노출 여부를 확인했습니다.
  • 테스트 및 빌드 결과를 확인했습니다.
  • 불필요한 코드와 디버깅 로그를 제거했습니다.

@claude

claude Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@ryuyejun
ryuyejun changed the base branch from main to develop October 25, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant