-
Notifications
You must be signed in to change notification settings - Fork 3
Feature : 이메일 인증 기능 구현 #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
추후, 다른 서비스에서 이메일 인증이 필요할 때도 가져다가 쓸 수 있음
|
""" Walkthrough이 변경 사항은 이메일 인증 기능을 대폭 확장합니다. 인증 코드 발송 및 검증을 위한 API 엔드포인트, DTO, 서비스 메서드, 예외 코드, 사용자 엔터티 필드, Redis 기반 인증 코드 저장 및 검증 로직이 추가·수정되었습니다. 기존 컨트롤러는 삭제되고, 새로운 구조로 통합되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant AuthController
participant AuthService
participant MailService
participant Redis
participant User
Client->>AuthController: POST /email/send
AuthController->>AuthService: sendEmailCode(userId, email)
AuthService->>MailService: sendMail(userId, email)
MailService->>MailService: createNumber(userId)
MailService->>Redis: set(code, TTL=3분)
MailService->>MailService: CreateMail(userId, email)
MailService->>MailService: 이메일 전송
AuthService-->>AuthController: SendEmailCodeResponse
AuthController-->>Client: 201 Created, 응답
Client->>AuthController: PUT /email/verify {code}
AuthController->>AuthService: verifyEmailCode(userId, code)
AuthService->>MailService: verifyCode(userId, code)
MailService->>Redis: get(code)
MailService-->>AuthService: 검증 결과 (true/false)
AuthService->>User: setVerified() (성공 시)
AuthService-->>AuthController: VerifyEmailCodeResponse
AuthController-->>Client: 200 OK, 응답
Possibly related PRs
Suggested reviewers
Poem
""" 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
src/main/java/org/ezcode/codetest/domain/user/service/MailService.java (1)
46-48: 예외 처리 개선 필요.현재 예외를 단순히 printStackTrace()로 처리하고 있어 적절한 에러 핸들링이 필요합니다.
다음과 같이 개선하세요:
} catch (MessagingException e) { - e.printStackTrace(); + log.error("Failed to create email message for user: {}", userId, e); + throw new RuntimeException("이메일 생성에 실패했습니다.", e); }
🧹 Nitpick comments (9)
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java (1)
3-5: 사용되지 않는 imports를 제거하세요.이메일 인증 관련 DTO들(
VerifyEmailCodeRequest,VerifyEmailCodeResponse,SendEmailCodeResponse)과PostMapping을 import하고 있지만, 실제로는 이 컨트롤러에서 사용되지 않습니다. AI 요약에 따르면 이메일 인증 기능은AuthController로 이관되었으므로 이 imports들을 제거해야 합니다.-import org.ezcode.codetest.application.usermanagement.auth.dto.request.VerifyEmailCodeRequest; -import org.ezcode.codetest.application.usermanagement.auth.dto.response.SendEmailCodeResponse; -import org.ezcode.codetest.application.usermanagement.auth.dto.response.VerifyEmailCodeResponse; -import org.springframework.web.bind.annotation.PostMapping;Also applies to: 18-18
src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java (4)
7-9: 사용되지 않는 이메일 인증 관련 imports를 제거하세요.
VerifyEmailCodeRequest,SendEmailCodeResponse,VerifyEmailCodeResponseDTO들을 import하고 있지만, 이 서비스 클래스에서는 실제로 사용되지 않습니다.-import org.ezcode.codetest.application.usermanagement.auth.dto.request.VerifyEmailCodeRequest; -import org.ezcode.codetest.application.usermanagement.auth.dto.response.SendEmailCodeResponse; -import org.ezcode.codetest.application.usermanagement.auth.dto.response.VerifyEmailCodeResponse;
19-19: 사용되지 않는 예외 관련 imports를 제거하세요.
UserException과UserExceptionCode를 import하고 있지만, 이 서비스 클래스에서는 실제로 사용되지 않습니다.-import org.ezcode.codetest.domain.user.exception.UserException; -import org.ezcode.codetest.domain.user.exception.code.UserExceptionCode;Also applies to: 21-21
25-25: 사용되지 않는 MailService 의존성을 제거하세요.
MailService를 import하고 dependency injection하고 있지만, 이 서비스 클래스에서는 실제로 사용되지 않습니다. 이메일 인증 기능이AuthService로 이관되었다면 이 의존성도 제거해야 합니다.-import org.ezcode.codetest.domain.user.service.MailService; - private final MailService mailService;Also applies to: 44-44
32-32: 사용되지 않는 @Valid import를 제거하세요.
@Valid어노테이션을 import하고 있지만, 이 클래스에서는 실제로 사용되지 않습니다.-import jakarta.validation.Valid;src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java (4)
52-52: 메소드명 오타 수정 필요:Registeration→Registration
userRegisterationProcess메소드명에 오타가 있습니다. 올바른 철자는Registration입니다.-userRegisterationProcess(request); +userRegistrationProcess(request);-private void userRegisterationProcess(SignupRequest request) { +private void userRegistrationProcess(SignupRequest request) {Also applies to: 67-67
63-63: 불필요한 세미콜론 제거if문 블록 뒤의 세미콜론은 불필요합니다.
- }; + }
102-105: 인증 코드 유효 시간 안내 추가 권장PR 설명에 따르면 인증 코드의 유효 시간이 3분으로 설정되어 있습니다. 사용자 경험 향상을 위해 응답 메시지에 유효 시간을 포함하는 것이 좋습니다.
- return SendEmailCodeResponse.from("인증 코드를 전송했습니다."); + return SendEmailCodeResponse.from("인증 코드를 전송했습니다. 3분 이내에 인증을 완료해주세요.");
192-192: 불필요한 디버깅 로그 제거PR 체크리스트에 따라 불필요한 로그를 제거해야 합니다.
- log.info("서비스 입장");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/request/VerifyEmailCodeRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/SendEmailCodeResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/SignupResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/VerifyEmailCodeResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java(5 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java(4 hunks)src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java(5 hunks)src/main/java/org/ezcode/codetest/domain/user/service/MailService.java(2 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/AuthController.java(3 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/MailCheckController.java(0 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/UserController.java(2 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/org/ezcode/codetest/presentation/usermanagement/MailCheckController.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (16)
src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java (1)
14-14: 이메일 인증 코드 불일치 예외 추가가 적절합니다.새로운
NOT_MATCH_CODE예외 코드가 이메일 인증 기능에 맞게 적절히 추가되었습니다. HTTP 상태 코드와 메시지가 적절하게 설정되었고, 기존 패턴과 일관성을 유지하고 있습니다.src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/SignupResponse.java (1)
7-8: 회원가입 응답 구조 변경이 적절합니다.회원가입 시 토큰을 즉시 반환하지 않고 완료 메시지만 반환하는 방식으로 변경된 것은 보안 관점에서 적절한 접근입니다. 이메일 인증 기능과 함께 사용자가 인증 완료 후 별도로 로그인하도록 하는 플로우가 더 안전합니다.
Also applies to: 10-11
src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/VerifyEmailCodeResponse.java (1)
1-13: 이메일 인증 코드 검증 응답 DTO가 적절하게 구현되었습니다.새로운
VerifyEmailCodeResponseDTO가 다른 응답 DTO들과 일관된 패턴으로 구현되었습니다. Swagger 어노테이션을 통한 API 문서화와 정적 팩토리 메서드 제공이 적절합니다.src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/response/SendEmailCodeResponse.java (1)
1-13: 깔끔한 응답 DTO 구현입니다.Record 클래스를 사용하여 불변성을 보장하고, 정적 팩토리 메서드와 Swagger 문서화가 적절히 구현되었습니다.
src/main/java/org/ezcode/codetest/application/usermanagement/auth/dto/request/VerifyEmailCodeRequest.java (1)
1-13: 적절한 요청 DTO 구현입니다.검증 어노테이션과 한국어 오류 메시지가 적절히 적용되었고, Lombok을 활용하여 코드가 간결합니다.
src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (4)
74-74: 이메일 인증 필드 추가가 적절합니다.이메일 인증 상태를 추적하기 위한
verified필드 추가가 적절하며, 주석으로 용도가 명확히 설명되어 있습니다.
93-94: 기본값 설정이 올바릅니다.새로 가입하는 사용자의 이메일 인증 상태를
false로 초기화하는 것이 논리적으로 적절합니다.Also applies to: 110-111
156-158: 인증 상태 업데이트 메서드가 적절합니다.
setVerified()메서드를 통해 이메일 인증 완료 시 상태를 업데이트할 수 있도록 구현되었습니다.
117-117: 생성자 호출 검색을rg로 재확인합니다.#!/bin/bash # 코드베이스에서 User 생성자 직접 호출 부분 검색 rg -n --glob '*.java' 'new User\(' .src/main/java/org/ezcode/codetest/presentation/usermanagement/AuthController.java (3)
5-5: 새로운 DTO import가 적절합니다.이메일 인증 기능을 위한 DTO 클래스들이 적절히 import되었습니다.
Also applies to: 8-8, 12-12, 22-22
82-88: 이메일 코드 전송 엔드포인트가 잘 구현되었습니다.RESTful API 설계에 맞게 POST 메서드를 사용하고, 201 Created 상태코드를 반환하며, 인증된 사용자의 정보를 적절히 활용합니다.
90-97: 이메일 코드 검증 엔드포인트가 적절합니다.PUT 메서드를 사용하여 사용자의 인증 상태를 업데이트하는 의미를 잘 표현했고, 요청 데이터 검증도 적절히 적용되었습니다.
src/main/java/org/ezcode/codetest/domain/user/service/MailService.java (2)
3-3: Redis 통합과 의존성 추가가 적절합니다.Redis를 활용한 인증코드 저장 및 로깅 기능 추가가 잘 구현되었습니다.
Also applies to: 6-6, 13-13, 15-15, 20-20, 25-25
27-30: 메서드 시그니처 변경이 적절합니다.
userId를 추가하여 사용자별로 인증코드를 관리할 수 있도록 개선되었습니다.src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java (2)
120-137: 토큰 생성 로직 추출 잘 되었습니다토큰 생성 로직을 별도의 private 메소드로 추출하여 코드 재사용성과 가독성이 향상되었습니다.
111-118: 추가 구현 확인을 위해getUserById메소드 본문을 출력해 주세요.#!/bin/bash # UserDomainService.getUserById 구현 출력 rg -n "public User getUserById" -A 20 src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java
| public String createNumber(Long userId) { | ||
| String verificationCode = generateRandomCode(); | ||
| String redisKey = "VERIFY_CODE:" + userId; | ||
|
|
||
| redisTemplate.opsForValue().set( | ||
| redisKey, | ||
| verificationCode, | ||
| EXPIRATION_MINUTES, | ||
| TimeUnit.MINUTES | ||
| ); | ||
| return verificationCode; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
인증코드 생성 및 Redis 저장 로직 개선 필요.
Redis 키 네이밍과 TTL 설정은 적절하지만, 몇 가지 개선이 필요합니다.
다음과 같이 개선하는 것을 권장합니다:
public String createNumber(Long userId) {
String verificationCode = generateRandomCode();
String redisKey = "VERIFY_CODE:" + userId;
+ try {
redisTemplate.opsForValue().set(
redisKey,
verificationCode,
EXPIRATION_MINUTES,
TimeUnit.MINUTES
);
+ } catch (Exception e) {
+ log.error("Failed to store verification code in Redis for user: {}", userId, e);
+ throw new RuntimeException("인증코드 저장에 실패했습니다.");
+ }
return verificationCode;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public String createNumber(Long userId) { | |
| String verificationCode = generateRandomCode(); | |
| String redisKey = "VERIFY_CODE:" + userId; | |
| redisTemplate.opsForValue().set( | |
| redisKey, | |
| verificationCode, | |
| EXPIRATION_MINUTES, | |
| TimeUnit.MINUTES | |
| ); | |
| return verificationCode; | |
| } | |
| public String createNumber(Long userId) { | |
| String verificationCode = generateRandomCode(); | |
| String redisKey = "VERIFY_CODE:" + userId; | |
| try { | |
| redisTemplate.opsForValue().set( | |
| redisKey, | |
| verificationCode, | |
| EXPIRATION_MINUTES, | |
| TimeUnit.MINUTES | |
| ); | |
| } catch (Exception e) { | |
| log.error("Failed to store verification code in Redis for user: {}", userId, e); | |
| throw new RuntimeException("인증코드 저장에 실패했습니다."); | |
| } | |
| return verificationCode; | |
| } |
🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/domain/user/service/MailService.java around
lines 55 to 66, improve the createNumber method by refining the Redis key naming
to follow a consistent and clear pattern, and ensure the TTL (expiration time)
is set using a constant or configuration value for easier maintenance. Also,
consider handling potential exceptions during Redis operations to avoid silent
failures. Update the method to incorporate these improvements accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@chat26666 사용자가 이메일로 받은 인증코드를 백엔드 서버로 전송하는 방법은 다음과 같습니다:
📧 이메일 인증 API 사용 방법
1️⃣ 인증코드 전송 요청
POST /auth/email/send
Authorization: Bearer {access_token}2️⃣ 인증코드 검증 요청
PUT /auth/email/verify
Authorization: Bearer {access_token}
Content-Type: application/json
{
"verificationCode": "123456"
}🔄 전체 인증 흐름
- 사용자가 인증코드 요청: 클라이언트에서
/auth/email/send엔드포인트 호출 - 서버가 이메일 전송: 6자리 인증코드가 사용자 이메일로 전송됨
- 사용자가 인증코드 확인: 이메일에서 받은 인증코드를 확인
- 클라이언트가 인증코드 전송:
/auth/email/verify엔드포인트로VerifyEmailCodeRequest형태로 전송 - 서버가 검증 완료: 인증코드가 일치하면 사용자의
verified상태가true로 업데이트
💡 주요 특징
- 인증 필요: 두 엔드포인트 모두
@AuthenticationPrincipal을 사용하여 로그인된 사용자만 접근 가능 - 자동 만료: Redis에 저장된 인증코드는 3분 후 자동 만료
- 일회성 사용: 인증 성공 시 Redis에서 코드가 자동 삭제됨
이 방식으로 프론트엔드에서는 사용자가 입력한 인증코드를 JSON 형태로 PUT 요청을 통해 서버에 전송할 수 있습니다! 🐰
🏁 Script executed:
#!/bin/bash
# AuthController의 이메일 인증 관련 엔드포인트 구현 확인
cat src/main/java/org/ezcode/codetest/presentation/usermanagement/AuthController.java
Length of output: 4773
@chat26666 AuthController 코드를 확인했습니다! 정확한 API 엔드포인트는 다음과 같습니다:
📧 정확한 이메일 인증 API 엔드포인트
1️⃣ 인증코드 전송 요청
POST /api/email/send
Authorization: Bearer {access_token}응답: SendEmailCodeResponse (인증코드 전송 성공 메시지)
2️⃣ 인증코드 검증 요청
PUT /api/email/verify
Authorization: Bearer {access_token}
Content-Type: application/json
{
"verificationCode": "123456"
}응답: VerifyEmailCodeResponse (인증 성공 메시지)
🔄 사용자 관점에서의 전체 흐름
- 로그인 후 → 액세스 토큰 보유 상태
- 인증코드 요청 →
POST /api/email/send호출 - 이메일 확인 → 받은 6자리 인증코드 확인
- 프론트엔드에서 입력 → 사용자가 인증코드 입력 폼에 코드 입력
- 백엔드로 전송 →
PUT /api/email/verify로 JSON 형태로 전송 - 인증 완료 → 사용자 계정이
verified: true상태로 업데이트
💻 프론트엔드 구현 예시
// 인증코드 전송
const sendCode = async () => {
const response = await fetch('/api/email/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
};
// 인증코드 검증
const verifyCode = async (code) => {
const response = await fetch('/api/email/verify', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
verificationCode: code
})
});
};이렇게 구현하면 사용자가 이메일에서 확인한 인증코드를 안전하게 백엔드로 전송할 수 있습니다! 🐰✨
src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java
Outdated
Show resolved
Hide resolved
|
사용자 입장에서 인증코드를 메일로 확인하면 백엔드 서버로 그 인증번호를 보내는 방법은 뭔가요? |
좀 코드를 봤는데요 사용자가 직접 인증코드를 제출해야하는 거같은데 그냥 이메일 내용물에다가 랜덤코드를 주는거보단 링크주소+인증코드 get 방식으로 보내서 바로 인증처리할 수 있게끔하는것도 괜찮지 않을까요 ? 보통 요즘 이메일 인증시스템 써보면 링크 띡 던져주고 링크 누르면 바로 인증되는 것처럼요 |
|
경오님이 말씀하신 방식이 프론트 화면을 따로 구현하지 않아도 되서 개인적으로 괜찮아 보이긴 합니다. 일단 두 방법 모두 장단점 있는 것 같네요! |
작업 내용
변경 사항
트러블 슈팅
1. 회원가입 후 바로 이메일 인증을 받게 할지, 아니면 추후에 특정 서비스를 이용할 때 받게 할지 결정 필요
선택한 방법
: 회원가입만으로 대부분의 서비스를 이용 가능
→ 이메일 인증을 완료해야 AI 코드리뷰 기능 사용 가능
장점 :
단점
2. 인증 코드 저장 방식에 대한 고민
선택한 방식
: Redis를 이용해 인증 코드 저장
참고 사항
verifed컬럼이 새로 생겼습니다,,, DB 재생성 권장드립니다코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit