Skip to content

[인증] 자동로그인 기능 적용 #829

@prgmr99

Description

@prgmr99

feat: 자동 로그인(Auto-Login) 구현

배경 및 문제점

현재 앱은 OAuth 로그인 후 accessTokenrefreshToken을 쿠키에 저장하지만, 실제로 refreshToken을 활용하는 로직이 전혀 없습니다. 이로 인해 아래와 같은 문제가 발생합니다.

  • 브라우저 새로고침 또는 탭 재방문 시: accessToken 쿠키가 만료되면 바로 로그인 페이지로 리다이렉트됨
  • 모바일 앱 재실행 시: WebView 쿠키가 유지되지 않아 매번 소셜 로그인 재요구
  • 401 에러 발생 시: 자동 갱신 없이 단순 에러 throw → UX 단절

목표

앱 재진입 시 사용자가 소셜 로그인 버튼을 다시 클릭하지 않아도 자동으로 인증 상태가 복원된다.

  • accessToken 유효 → 자동 로그인
  • accessToken 만료 + refreshToken 유효 → 무음 갱신(Silent Refresh) 후 자동 로그인
  • refreshToken까지 만료 → 로그인 페이지 이동

구현 범위

신규 파일 (2개)

apps/web/src/lib/auth-event.ts

  • Axios 인터셉터(React 컨텍스트 외부)에서 React Router 네비게이션을 이벤트로 연결하는 브릿지

apps/web/src/api/token.ts

  • refreshAccessToken(): POST /api/auth/reissue-token 호출
    • 헤더: Refresh: {refreshToken}
    • 바디: { member_id: number }
    • Promise 공유 패턴으로 동시 다발 호출 시 API 1회만 발생
  • clearAuthCookies(): 인증 쿠키 일괄 제거 유틸

수정 파일 (8개)

파일 변경 내용
apps/web/src/api/index.ts onErrorResponse async화, 401을 switch 이전에 가로채어 토큰 갱신 후 원래 요청 재시도
apps/web/src/layout/RequireLoginLayout.tsx refreshToken 기반 복원 로직, 갱신 중 로딩 UI, auth-event 리스너 등록
apps/web/src/config/storage-keys.ts COOKIE_KEYS.accessToken, refreshToken, memberId 상수 추가
apps/web/src/hooks/api/login/usePostSignOut.ts 로그아웃 API 실패 시에도 로컬 쿠키/상태 정리
apps/web/src/hooks/api/login/usePostSignIn.ts 쿠키 키 상수 사용
apps/web/src/hooks/api/login/usePostSignUp.ts 쿠키 키 상수 사용
apps/web/src/hooks/api/login/usePostAppleToken.ts 쿠키 키 상수 사용
apps/web/src/hooks/api/user/useDeleteUser.ts 중복 Authorization 헤더 제거 (인터셉터에 위임)
apps/mobile/layout/webview-layout/index.tsx sharedCookiesEnabled, thirdPartyCookiesEnabled 추가

기술적 설계 포인트

401 자동 갱신 인터셉터

API 호출 → 401 응답
    ↓
이미 재시도한 요청? (WeakSet 확인)
    YES → clearAuthCookies() + 로그인 이동
    NO  → refreshAccessToken() 호출
            ↓ 성공: 새 토큰으로 원래 요청 재시도
            ↓ 실패: clearAuthCookies() + 로그인 이동

동시 다발 401 처리

  • refreshPromise 싱글턴으로 토큰 갱신 API는 항상 1회만 호출
  • 갱신 실패 직후 2초 쿨다운으로 불필요한 재시도 방지

RequireLoginLayout 복원 흐름

마운트
    ↓
isLogin=true + accessToken 쿠키 있음? → 즉시 통과
isLogin=true + accessToken 없음?      → refreshToken으로 갱신 시도
isLogin=false + accessToken 있음?     → /member-info로 사용자 정보 복원
accessToken 없음 + refreshToken 있음? → 갱신 후 사용자 정보 복원
둘 다 없음?                           → /login 이동
    ↓
갱신 중: LoadingModal 표시 (빈 화면 깜빡임 방지)

엣지 케이스

시나리오 동작
동시 다발 401 갱신 1회만 발생, 이후 요청은 새 토큰으로 재시도
refreshToken 만료 로그인 페이지 이동, 현재 경로 prev-path 쿠키 저장
로그아웃 API 실패 로컬 쿠키/상태 강제 정리 후 로그인 이동
모바일 앱 강제 종료 후 재실행 sharedCookiesEnabled로 쿠키 유지 → 자동 복원
isLogin=true + 쿠키 없음 (상태 불일치) refreshToken 확인 후 갱신 또는 로그인 이동

참고

  • 활용 API: POST /api/auth/reissue-token (헤더: Refresh, 바디: { member_id })
  • 응답에 전체 사용자 정보 포함 → 갱신 후 별도 /member-info 호출 불필요

체크리스트

  • 브라우저 재방문 시 accessToken 유효하면 자동 로그인
  • accessToken 만료 시 refreshToken으로 무음 갱신
  • refreshToken 만료 시 로그인 페이지 이동
  • 갱신 중 LoadingModal 표시
  • 동시 다발 401에서 갱신 API 1회만 호출
  • 로그아웃 후 자동 로그인 안 됨
  • iOS 앱 재실행 후 로그인 유지
  • Android 앱 재실행 후 로그인 유지
  • TypeScript 빌드 에러 없음

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions