Skip to content

feat(#198): 회원 탈퇴(계정 삭제) API 구현 - #199

Merged
fnzl54 merged 3 commits into
devfrom
feat/#198
Aug 12, 2026
Merged

fnzl54 merged 3 commits into
devfrom
feat/#198

Conversation

@fnzl54

@fnzl54 fnzl54 commented Aug 12, 2026

Copy link
Copy Markdown
Member

연관 이슈

작업 사항

  • feat(#198): 회원 탈퇴 API 구현
    • 삭제 후 동일 소셜 계정으로 재로그인 시 신규 회원으로 가입 처리 (기획 확인 완료)
    • 리프레시 토큰 검증 → 소프트 삭제 → 개인정보 익명화 → 리프레시 토큰 삭제
      • AT/RT userId 일치,만료 여부,DB에 저장된 토큰과의 일치 여부 확인 후 회원 탈퇴 진행
      • 탈취된 AT만으로는 계정 삭제 불가능 (단 RT는 유저당 1개만 저장되어 다른 기기에서 재로그인하면 이전 기기의 RT가 무효화되므로, 그 기기는 AT가 유효해도 탈퇴가 막힐 수 있음)
  • feat(#198): 회원 탈퇴 시 Slack 알림 연동
    • 알림 전송 실패는 탈퇴 트랜잭션에 영향 없도록 예외 처리
  • refactor(#198): 탈퇴 회원 재조회 방지 및 User 조회 로직 통합
    • User 조회 로직을 ReadUserService로 통합
    • 가입 알림의 누적 가입자 수를 count() → countByDeletedFalse()로 변경하여 탈퇴 회원이 집계에서 제외

테스트

  • 로컬 서버 테스트 완료 (Slack 알림 테스트 완료)

주의 사항 및 참고사항

@fnzl54 fnzl54 self-assigned this Aug 12, 2026
Comment on lines +113 to +128
private void deleteUser(User user, Long userId) {
String nickName = user.getNickName();
User.Provider provider = user.getProvider();

user.softDelete();
user.deletePersonalInfo();
refreshTokenRepository.deleteByUserId(userId);

try {
notificationProvider.send(
new AccountDeleteNotificationMessage(userId, nickName, provider));
} catch (Exception e) {
log.warn("[DeleteUserService] 회원 탈퇴 슬랙 알림 전송 실패. userId: {}", userId, e);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] 회원 탈퇴 트랜잭션 내에서 동기 Slack 알림 호출

Problem: DeleteUserService는 클래스 레벨 @Transactional이 적용되어 있는데, deleteUser()에서 softDelete() / deletePersonalInfo() / refreshTokenRepository.deleteByUserId() 실행 직후 외부 Slack HTTP 호출(notificationProvider.send(...))을 같은 트랜잭션 안에서 동기적으로 수행합니다. Slack 응답 지연이 그대로 DB 커넥션 점유 시간에 더해져, 트래픽이 몰리는 시점에 커넥션 풀 고갈로 이어질 수 있습니다.

Evidence: 동일한 패턴이 회원가입 알림(PR #153)에서도 있었고, 당시 리뷰에서 동기식 외부 API 호출로 인한 성능/안정성 저하 문제로 지적된 뒤, 별도 후속 작업(이슈 #182, PR #183/#194 "slack 알림을 트랜잭션 비동기 처리")에서 @TransactionalEventListener(phase = AFTER_COMMIT) + @Async 조합으로 전환되었습니다. 이번 PR의 DeleteUserService.deleteUser() 113~128번째 줄은 try/catch로 알림 실패가 삭제 트랜잭션에 영향을 주지 않도록만 처리했을 뿐, 팀이 이미 확립한 비동기 처리 패턴은 적용하지 않았습니다.

Fix direction: 이미 온보딩 알림에 적용된 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @Async 리스너 패턴을 재사용해, 탈퇴 처리와 Slack 알림 전송을 분리하는 것을 권장합니다. deleteUser()에서 notificationProvider.send(...)를 직접 호출하는 대신 ApplicationEventPublisher로 AccountDeletedEvent를 발행하고, 별도의 AccountDeleteNotificationListener에서 @Async + @TransactionalEventListener(phase = AFTER_COMMIT)을 사용해 알림을 비동기로 전송하도록 옮겨주세요.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 PR에서는 현재 구현 유지

온보딩 완료 알림에 적용된 @TransactionalEventListener(phase = AFTER_COMMIT) + @Async 패턴으로 전환이 필요한 부분이라 회원가입 알림과 함께 별도 이슈/PR로 진행 예정

@fnzl54
fnzl54 merged commit fa572a5 into dev Aug 12, 2026
1 check passed
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.

2 participants