RoundWaitBugFixGo
RoundWait — 삭제된 사용자 재가입 시 충돌 버그 수정
2026. 6. 23.1분 읽기
버그 설명
프로젝트: RoundWait (Go)
어드민이 사용자를 삭제(soft-delete)한 뒤, 같은 전화번호로 재가입을 시도하면 로그인에 실패하는 문제.
근본 원인
getOrCreatePhoneUserCredential이 기존 자격증명을 조회할 때 GORM의 기본 soft-delete 필터(WHERE deleted_at IS NULL)만 적용됐다. 연결된 Account나 UserProfile이 soft-delete된 경우는 필터에서 제외됐고, 삭제된 자격증명이 "유효한 기존 유저"로 반환돼 로그인 흐름이 막혔다.
수정 내용
1. GORM 조회를 Unscoped()로 변경
// After — 삭제된 레코드도 포함해서 조회
s.db.Unscoped().
Preload("Account", func(db *gorm.DB) *gorm.DB { return db.Unscoped() }).
Preload("UserProfile", func(db *gorm.DB) *gorm.DB { return db.Unscoped() }).
Where("event_id = ?", eventId).
Where("phone_number_text IN ?", lookupCandidates).
First(&existingCred)
2. isDisabledPhoneCredential 검사 추가
조회된 자격증명이 비활성 상태인지 판단.
3. 비활성 자격증명 아카이빙
삭제된 자격증명의 번호를 phone#disabled:id 형식으로 변경해서 충돌을 방지하고 새 자격증명 생성을 허용.
4. active_session_guard.go 추가
로그인 세션 유효성 검사 미들웨어. 세션이 살아있어도 관련 계정/프로필이 삭제된 경우 401 반환.
테스트 추가
phone_number_service_test.go와 user_delete_cleanup_test.go에 테스트 케이스 추가 (총 16개 파일 변경, +706 줄).
교훈
GORM의 soft-delete 필터는 연관 테이블에 자동 적용되지 않는다. Preload 안에서 별도로 Unscoped()를 명시해야 삭제된 연관 레코드까지 가져올 수 있다.