로그인 개발 명세 (FRD)¶
요지¶
JWT 로그인·로그아웃·토큰 재발급을 어떻게 구현하는지 정리한다. 세 역할이 같은 이메일·비밀번호 인증을 쓰고, 통과하면 Access·Refresh 두 토큰을 발급한다. Refresh는 JS가 손대지 못하도록 HttpOnly 쿠키에만 담는다. 계정 상태 전이와 실패 횟수에 따른 잠금은 모두 서버가 책임진다 — 클라이언트를 믿지 않는다는 원칙이다.
상위 PRD (링크 · 변경 시 알림)¶
기획은 prd(바뀌면 이 문서도 갱신), 회원 도메인(Member/Status/Role)은 member가 단일 기준이다.
기술 접근 · 아키텍처¶
토큰·세션 정책¶
토큰 수명과 서명 키 같은 실제 값은 인프라 설정(infra)에 두고, 여기서는 정책의 뼈대만 다룬다.
- Access / Refresh 2종: Access는 짧게, Refresh는 길게 산다. Refresh는
HttpOnly + Secure + SameSite=Lax쿠키로만 저장해 JS가 읽지 못하게 막는다. - 재발급: Access 만료 인식 즉시 FE가
/api/auth/refresh호출(Refresh 쿠키 자동 전송) → 신규 Access 쿠키 수신 → 원요청 재시도. Refresh 갱신 실패 시 즉시 로그아웃. - CSRF 방어: SameSite 쿠키 + 서버 토큰 검증.
- "로그인 상태 유지": ON → Refresh 영속 쿠키(자동 로그인), OFF → 세션(메모리/Session Storage)에만 유지.
- 계정 잠금: 비밀번호 5회 연속 실패 →
status=LOCKED. 관리자가 직접LOCKED설정도 가능. 상태는users.status컬럼으로 관리.
처리흐름¶
로그인 요청 → BE 이메일/비번 검증
├ 일치 + ACTIVE → Access/Refresh 발급 → 200 + 쿠키 → FE /dashboard
├ 불일치 → login_fail_count += 1 → 401 (5회 도달 시 status=LOCKED)
└ 상태 이상 → INACTIVE 403 / LOCKED 423·403 / WITHDRAWN 403
로그아웃 → Refresh 무효화·쿠키 만료·세션(Redis) 삭제 → 204
Access 만료 → FE /api/auth/refresh → 신규 Access 쿠키 → 원요청 재시도
재설정 성공 시 status=ACTIVE + login_fail_count=0 초기화. 로그인 성공 시에도 카운트 0 초기화.
API · 데이터 모델¶
인증은 로그인·로그아웃·재발급 세 엔드포인트로 끝난다.
| 동작 | 엔드포인트 | 비고 |
|---|---|---|
| 로그인 | POST /api/auth/login |
성공 200 + 토큰/사용자 정보, 실패 401 |
| 로그아웃 | POST /api/auth/logout |
Refresh 무효화(블랙리스트/DB 컬럼)·쿠키 만료·세션 삭제, 204/200 |
| 토큰 재발급 | POST /api/auth/refresh |
Refresh 쿠키 검증 → 신규 Access 발급 |
- 데이터: Member
email(unique)·password·role·status·last_login_at·login_fail_count. 상세 컬럼은 member §2. - 상태 전이:
ACTIVE --실패5회--> LOCKED,LOCKED --비번재설정--> ACTIVE,INACTIVE --이메일인증--> ACTIVE,WITHDRAWN은 로그인 제한.
예외·검증¶
미입력·형식 오류 같은 클라이언트 단의 문제는 공용 검증 규칙(V-01~02·05 등)에서 걸러 서버까지 보내지 않는다. 규칙 전체는 회원가입 개발 명세 (FRD)가 기준이다.
서버가 막을 때는 상태에 따라 메시지를 달리한다. 비밀번호가 틀리면 401("이메일 또는 비밀번호가 올바르지 않습니다"), 이메일 인증 전이면 403/INACTIVE, 잠긴 계정이면 423/LOCKED("계정이 잠겼습니다. 비밀번호를 재설정하거나 관리자에게 문의해주세요"), 탈퇴 계정이면 403/WITHDRAWN이다.
로그아웃은 보안이 우선이라, 네트워크가 실패해도 일단 프런트의 로컬 세션부터 비우고 /login으로 보낸다. 보호된 화면은 들어올 때마다 인증을 다시 확인한다.
의존성 · 영향 범위¶
- member 도메인(상태·역할·실패 카운트), 세션 캐시(infra Redis), 공용 Validation(회원가입 개발 명세 (FRD) §5).
- 잠금 해제는 계정 복구 (Account Recovery) 비밀번호 재설정 경유.
테스트 계획¶
공통 케이스·E2E 전략은 qa-playbook을 따른다. 이 기능에서 꼭 볼 것은 로그인 성공·401·계정 상태별 분기, 5회 실패 잠금, refresh 재발급, 그리고 로그아웃 뒤 보호된 화면에 다시 들어갈 때의 인증 재검사다.
행동 분석용 GA 이벤트는 로그인 흐름의 각 단계마다 심어 둔다. 어디서 막히고 어디서 이탈하는지를 보기 위해서다.
| 단계 | 이벤트(예) |
|---|---|
| 진입·상호작용 | auth_page_view · auth_input_interact · auth_focus_*_field · auth_toggle_password_visibility · auth_toggle_remember_me |
| 제출·결과 | auth_submit_login · auth_login_api_call · auth_login_success · auth_login_failure |
| 실패·잠금 | auth_client_validation_failure · auth_error_message_view · auth_retry_login · auth_captcha_shown · auth_account_locked_notice |
| 자동/세션 | auth_auto_login_success · auth_auto_login_failure · auth_session_expired_redirect |
| 로그아웃 | auth_click_logout · auth_logout_success · auth_logout_network_error · auth_protected_route_redirect · auth_session_clear |
작업 분해 (이슈 링크)¶
진행·완료 상태는 status와 GitHub 이슈에서 확인한다. 관련 이슈: Jira BTS-244.