계정 연동 과정에서 마찰 없는 로그인 경험 설계
문제 정의
현재 로그인 화면은 이메일 입력 → 비밀번호 입력을 고정 전제로 동작한다.
하지만 accountLinking 구조에서는 소셜로만 가입한 사용자도 존재하며, 이들은 비밀번호가 없다.
이 상태에서 비밀번호 입력을 요구하면 로그인 성공 가능성이 없는 경로로 사용자를 보내게 된다.
왜 이게 실제 문제인가
입력 UI는 단순하지만, 실제 계정 상태는 분기형이다.
이메일+비밀번호 계정
소셜 only 계정
여러 provider가 링크된 계정 (google, reddit, kakao 등)
즉, 같은 이메일이어도 인증 경로가 다르다.
프론트가 이를 반영하지 않으면 사용자는 틀린 비밀번호를 반복 시도하고, 왜 실패하는지 이해하지 못한 채 이탈할 가능성이 커진다.
해결 목표
이번 개선의 목표는 세 가지다.
소셜 only 계정을 비밀번호 단계로 보내지 않는다.
사용자가 추가 선택(버튼 재클릭 등) 없이 가능한 경로로 자동 진행한다.
자동 진행이 실패해도 플로우를 깨지 않고, 현재 단계에서 실패 이유를 즉시 이해하게 한다.
해결 방식: Identifier-first
핵심 아이디어는 identifier-first(이메일 우선 판별)이다.
이메일을 입력받는 즉시, 다음 단계가 비밀번호인지 소셜인지 먼저 결정한다.
POST /api/auth/email-sign-in-intent body: { email }백엔드는 다음 순서로 판단한다.
user + account 조회
소셜 provider가 하나 이상이면 SOCIAL_REDIRECT 반환
여러 provider가 있으면 createdAt 기준 첫 번째 provider 선택
소셜이 없으면 PASSWORD 반환
클라이언트는 응답에 따라 분기한다.
if (intent.nextAction === "SOCIAL_REDIRECT") { signIn.social(...) } else { step = "password" }UX 원칙과 변경점
초기에는 “자동 소셜 실패 시 비밀번호 단계로 강제 이동”도 검토했지만, 이 방식은 사용자 의도와 문맥을 잃게 만든다.
최종적으로는 현재 단계 유지 + 명확한 에러 노출로 정리했다.
실패 시 step=password 강제 fallback 금지
이메일 단계에서 바로 에러 표시
에러 위치는 이메일 필드 바로 아래
Continue 버튼은 요청 중 스피너 표시 + disabled 처리
Google 연동에서의 현실 제약과 대응
소셜 자동 진입 시 Google 계정 선택 화면이 다시 뜰 수 있어, “이메일을 입력했는데 왜 또 선택해야 하지?”라는 피로가 생긴다. 이를 줄이기 위해 다음을 적용했다.
socialProviders.google.prompt = “none”
자동 소셜 시도는 disableRedirect: true로 결과를 직접 확인
실패하면 /sign-in으로 복귀하고 이메일 단계 에러를 그대로 유지
최종 플로우
사용자가 이메일 입력
백엔드가 인증 경로 판별
소셜 계정이면 자동 소셜 시도
성공 시 즉시 인증 진행
실패 시 이메일 단계 유지 + 에러 표시
비밀번호 계정(또는 신규)만 비밀번호 단계 진입
본질은 “입력 UI 중심”이 아니라 “계정 상태 중심”으로 로그인 흐름을 재설계한 것이다.
그 결과로 소셜 only 사용자를 잘못된 비밀번호 경로로 보내지 않고 자동 분기와 명확한 실패 피드백을 통해 로그인 경험을 더 자연스럽게 만들 수 있다.