공부일지/프로젝트

[트러블 슈팅] OAuth2 플랫폼 별 Email 같을 때 다른계정으로 로그인 되는 문제

박수빈98 2025. 7. 18. 16:36

Refresh Token을 적용하고 테스트하는 과정에서 다음과 같은 문제 발생하였다.

문제 요약

  • A 사용자가 Google로 test@gmail.com 가입
  • B 사용자가 Kakao로 동일 이메일로 로그인 시도 → A 계정으로 로그인 처리됨
  • 이유: 이메일이 유일한 값으로 설정되어 있어 provider 구분 없이 하나의 계정으로 인식됨

해결 전략

  • User 엔티티에 provider 필드(enum)를 추가
  • 로그인 시 email + provider 조합으로 비교는 하지 않음
  • email만을 기준으로 중복 여부를 판단하고, 이미 존재할 경우 해당 provider 정보를 포함한 에러 응답 반환

API 응답 예시

{
  "success": false,
  "message": "GOOGLE로 가입된 이메일입니다.",
  "data": {
    "email": "test@gmail.com",
    "provider": "GOOGLE"
  },
  "errorCode": "U001",
  "statusCode": 409,
  "timestamp": "..."
}

만약 ID/PW로 일반 회원가입 한 경우는

{
  "success": false,
  "message": "LOCAL로 가입된 이메일입니다.",
  "data": {
    "email": "subin4420@gmail.com",
    "provider": "LOCAL"
  },
  "errorCode": "U001",
  "statusCode": 409,
  "timestamp": "2025-07-18T16:26:04.517582"
}

장점

  • 이메일 기준 단일 계정 유지
  • 소셜 계정 중복 생성을 방지
  • 프론트에서 사용자에게 정확한 로그인 플랫폼 안내 가능
  • DB에서 복합키 없이 로직으로 관리 가능

단점

  • 탈퇴 후 재가입 시 기존 플랫폼 정보를 사용자가 기억하지 못할 수 있음 → DB에 Provider 저장으로 해결
  • 가입 플랫폼 정보를 UI에 표시하지 않으면 사용자가 혼란을 겪을 수 있음 → 응답으로 provider 제공해 어떤 이메일이 어떤 플랫폼으로 가입되었는지 안내

결론

  • 하나의 이메일로 하나의 계정만 허용
  • 이미 가입된 이메일인 경우, 어떤 플랫폼(provider)으로 가입되어 있는지 명시하여 에러 응답
  • provider는 필수로 저장하며, LOCAL(ID/PW)과 소셜 로그인을 구분함

배운 점 정리

  1. 동일 이메일로 여러 플랫폼 가입을 허용하면 안 되는 이유: 계정 충돌
  2. provider는 필수 필드이며 null이 아닌 LOCAL, GOOGLE 등으로 명확히 구분
  3. 중복 가입 방지는 서버 로직으로 처리하고, 복합키 대신 에러 응답 설계로 유연하게 대응