refactor: sprint1 hardening#25
Conversation
- 회원 탈퇴 시 afterCommit 콜백으로 WithdrawalPolicy 적용 로직 추가 - 트랜잭션이 활성화되지 않은 경우 즉시 콜백 처리하도록 수정 - 테스트에 TransactionSynchronization 초기화 및 검증 로직 추가 - 회원 탈퇴 서비스 테스트에 tearDown 메서드로 트랜잭션 정리 코드 추가
- 탈퇴 시 트랜잭션 동기화가 없을 경우 즉시 후처리 동작 검증 - WithdrawalPolicy validate, apply 호출 및 Refresh Token 폐기 로직 검증 - 회원 상태 변경(MemberStatus.DELETED) 및 요청 컨텍스트 처리 확인
- RefreshTokenRepository에 PESSIMISTIC_WRITE 잠금 설정 및 테스트 케이스 작성 - 동시에 동일 RefreshToken 조회 시 대기 및 상태 갱신(ROTATED) 검증 - 트랜잭션 종료 후 다른 조회가 정상 동작하는지 확인 - 테스트 환경 설정에 flyway 비활성화 및 JPA ddl-auto=create-drop 추가
- EmailEncryptor 유틸 클래스와 EmailEncryptionConfig, Properties를 통해 암호화 키 설정 - 이메일 암호화 필드 추가(Member, UserSchoolVerification) 및 관련 엔티티 수정 - 이메일 암호화 저장(Signup) 및 복호화 처리(Query) 로직 추가 - 학교 이메일 인증 서비스에 암호화된 이메일 데이터 저장 로직 반영 - 테스트 코드 및 API 문서(MemberDocsTest) 수정 및 보완
- 이메일 인증 요청 시 UserSchoolVerification 상태가 PENDING인 항목 검증 로직 추가 - 상태 검증 실패 시 MemberErrorCode.SCHOOL_VERIFICATION_NOT_FOUND 예외 발생 처리 - SchoolEmailVerificationServiceTest에 관련 단위 테스트 추가 - 잘못된 학교 인증 요청 시 발생하는 예외 및 동작 검증 테스트 보완
- 학교 이메일 인증 메일 발송을 트랜잭션 커밋 이후로 지연 처리 - TransactionSynchronizationManager를 활용한 afterCommit 콜백 메서드 registerAfterCommit 추가 - SchoolEmailVerificationServiceTest에 이메일 발송 동작 검증 테스트 추가 - 테스트 정리(TearDown) 단계에서 트랜잭션 동기화 초기화 로직 추가
- 실패 시도 증가(failureRecorder.increaseAttempt) 로직을 검증 조건 내부로 이동 - 조건에 의한 의도치 않은 로직 실행 방지 위해 테스트 코드 수정 - 불필요한 Mock 및 verify 호출 제거로 테스트 단순화 - failureRecorder 및 tokenHasher 동작 검증 테스트 보완
|
요청하신 트리거/PR 정보를 확인했지만, 현재로서는 **구체적인 수정 요청(버그, 실패한 CI, 변경 지시 코멘트)**이 포함되어 있지 않아 적용할 코드 변경을 특정할 수 없었습니다. 제가 확인한 내용
따라서 이번 턴에서는 코드 수정, 커밋, 후속 PR 생성을 진행하지 않았습니다. 원하시면 다음 중 하나로 바로 진행할 수 있습니다:
|
|
@codex 코드 리뷰 모드 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 704c338361
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| val email = request.email.trim().lowercase() | ||
| val emailHash = emailHasher.hash(email) |
There was a problem hiding this comment.
이번 커밋에서 회원가입은 request.email.trim().lowercase()로 해시를 만들도록 바뀌었지만, 로그인(AuthLoginService.login)은 여전히 원문 request.email을 그대로 해시합니다. 그 결과 사용자가 가입 시 Test@Unit.com처럼 대소문자/공백이 섞인 이메일을 입력하면 DB에는 정규화된 해시가 저장되고, 이후 같은 입력값으로 로그인할 때 해시가 달라져 INVALID_LOGIN_CREDENTIALS가 발생합니다. 가입과 로그인에서 동일한 정규화 규칙을 공유하도록 맞춰야 합니다.
Useful? React with 👍 / 👎.
| override fun afterCommit() { | ||
| action() | ||
| } |
There was a problem hiding this comment.
afterCommit 콜백 예외를 탈퇴 응답과 분리하라
withdrawalPolicies.apply를 afterCommit에서 그대로 실행하면, 콜백 내부 예외가 호출자까지 전파되는 동안 DB 커밋은 이미 완료되어 회원은 DELETED 상태인데 API는 실패(5xx)로 보일 수 있습니다. 이 커밋에서 후처리를 트랜잭션 밖으로 이동했기 때문에 새로 생긴 불일치이며, 클라이언트 재시도/운영 모니터링에서 "실패처럼 보이지만 실제로는 탈퇴 완료" 상태를 만듭니다. 콜백 예외를 별도 처리(try-catch + 로깅/비동기 재처리)해 커밋 결과와 응답 의미를 분리하는 편이 안전합니다.
Useful? React with 👍 / 👎.
- 로그인 요청 시 이메일 입력값의 공백 제거 및 소문자 변환 처리 추가 - 이메일 해시 생성 전 불필요한 대소문자 및 공백 문제 방지 - MemberRepository 조회 시 일관된 이메일 데이터 사용 보장
- WithdrawalPolicy 적용 로직을 applyWithdrawalPoliciesAfterCommit 메서드로 분리 - 후처리 중 예외 발생 시 memberId 및 정책명을 포함한 에러 로그 추가 - 로그 처리를 위해 MemberWithdrawalService에 LoggerFactory 추가
- MemberWithdrawalService에 회원 동의 철회 처리 로직 추가 - MemberConsent 엔티티에 withdraw 메서드 추가 및 withdrawnAt 저장 처리 - MemberConsentRepository에 findAllByMemberId 메서드 추가 - 회원 탈퇴 서비스 테스트(MemberWithdrawalServiceTest)에 동의 철회 검증 로직 추가 - 트랜잭션 동기화 없는 상황에서도 동의 철회 동작 검증 테스트 보완
|
@codex 코드 리뷰 모드 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bd78f620d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| val email = request.email.trim().lowercase() | ||
| val emailHash = emailHasher.hash(email) |
There was a problem hiding this comment.
여기서 이메일을 trim().lowercase()로 정규화한 뒤 해시를 조회하면, 이 커밋 이전에 대소문자 그대로 해시 저장된 회원(예: User@school.ac.kr)은 동일 주소로 로그인해도 항상 다른 해시가 되어 INVALID_LOGIN_CREDENTIALS로 실패합니다. 즉 배포 시점부터 일부 기존 계정이 즉시 로그인 불가 상태가 될 수 있으므로, 최소한 데이터 백필(backfill) 완료 전까지는 기존 해시 포맷도 함께 조회하거나, 마이그레이션을 선행해 해시 일관성을 맞춰야 합니다.
Useful? React with 👍 / 👎.
| val email = request.email.trim().lowercase() | ||
| val emailHash = emailHasher.hash(email) |
There was a problem hiding this comment.
이메일 중복 검사에 레거시 해시 호환 경로를 추가하세요
회원가입에서 이메일을 소문자 정규화해 해시를 만들기 시작했지만 기존 데이터는 비정규화 해시를 그대로 가지고 있어, 과거에 대문자로 가입된 주소와 동일한 메일박스가 새로운 소문자 해시로 중복 가입될 수 있습니다. 이 경우 existsByEmailHashAndDeletedAtIsNull가 false가 되어 동일 실사용 이메일에 대해 활성 계정이 2개 생길 수 있으므로, 정규화 전/후 해시를 모두 차단하거나 사전 마이그레이션으로 기존 해시를 통합해야 합니다.
Useful? React with 👍 / 👎.
📌 작업 개요
여러 기술적 수정사항들 수정 및 테스트
🔗 관련 이슈
✨ 변경 사항
🧪 테스트
✅ 체크리스트
feature/,fix/,hotfix/등)💬 리뷰어에게
@codex