Skip to content

[feat] 비밀번호 재설정 페이지 및 토큰 재발급 기능 구현#39

Merged
dohy-eon merged 9 commits into
devfrom
feat/ALT-231
May 20, 2026
Merged

[feat] 비밀번호 재설정 페이지 및 토큰 재발급 기능 구현#39
dohy-eon merged 9 commits into
devfrom
feat/ALT-231

Conversation

@dohy-eon
Copy link
Copy Markdown
Member

@dohy-eon dohy-eon commented May 20, 2026

ID

  • ALT-231

변경 내용

  • 인증 API 연동 보완: 액세스 토큰 만료 시 자동 갱신, 로그아웃 서버 연동, 비밀번호 찾기 플로우 추가
  • 회원가입·비밀번호 찾기 시 이메일/휴대폰 중복 검사 및 Firebase ID 토큰 전달

구현 사항

  • 토큰·로그아웃
    • authInstance 401 응답 시 POST /app|manager/auth/token으로 refresh 후 원 요청 재시도 (동시 요청 큐 처리)
    • 마이페이지 로그아웃 시 POST /app|manager/auth/logout 호출 후 로컬 세션 정리
  • 비밀번호 찾기 (/find-password)
    • 3단계 UI: 이메일 입력 → SMS 인증 → 새 비밀번호 설정
    • password-reset/session, password-reset API 연동 (세션 생성 시 firebaseIdToken 포함)
  • 회원가입 보완
    • SMS/이메일 발송 전 exists/contact, exists/email 중복 검사
    • auth.ts에 공개 인증 API 함수 추가 (checkEmailDuplicate, checkContactDuplicate 등)
  • 기타
    • scope별 API 경로 매핑 (USER → app, MANAGER → manager)

구현 시연 (필요 시)

2026-05-20.3.58.05.mov

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 비밀번호 찾기 기능 추가: 이메일 입력 → 휴대폰 인증 → 비밀번호 재설정 3단계 흐름 구현
    • 가입 시 이메일 및 휴대폰 번호 중복 확인 기능 추가
    • SMS 인증 기능 강화 및 재발송 쿨다운 추가
  • Refactor

    • 인증 API 및 라우트 구조 개선
    • 토큰 갱신 로직 자동화로 안정성 향상
    • 로그아웃 프로세스 비동기 처리로 보안 강화

Review Change Stack

@dohy-eon dohy-eon requested review from kim3360 and limtjdghks May 20, 2026 07:04
@dohy-eon dohy-eon self-assigned this May 20, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
alter-client Ready Ready Preview, Comment May 20, 2026 8:28am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f39d19c3-5293-44e9-9125-6c3e96304f3c

📥 Commits

Reviewing files that changed from the base of the PR and between 5f39d29 and 815df6c.

📒 Files selected for processing (16)
  • src/features/auth/index.ts
  • src/features/auth/ui/PhoneVerification.tsx
  • src/features/auth/ui/VerifyActionButton.tsx
  • src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts
  • src/pages/find-password/index.tsx
  • src/pages/my/index.tsx
  • src/pages/signup/components/EmailVerification.tsx
  • src/pages/signup/components/Step1UserInfo.tsx
  • src/pages/signup/components/Step2AccountInfo.tsx
  • src/pages/signup/hooks/useEmailVerification.ts
  • src/pages/signup/hooks/usePhoneVerification.ts
  • src/shared/api/auth.ts
  • src/shared/hooks/index.ts
  • src/shared/hooks/useTimer.ts
  • src/shared/lib/axiosInstance.ts
  • src/shared/lib/utils/emailValidation.ts
✅ Files skipped from review due to trivial changes (3)
  • src/features/auth/index.ts
  • src/shared/hooks/index.ts
  • src/pages/signup/components/Step1UserInfo.tsx

📝 Walkthrough

Walkthrough

비밀번호 찾기 3단계 플로우(이메일→휴대폰 SMS 인증→비밀번호 재설정)를 새로 추가하고, 토큰 자동 갱신·401 재시도·로그아웃 서버 호출 및 회원가입 중복 확인 검증을 강화합니다.

Changes

비밀번호 찾기 기능

Layer / File(s) Summary
비밀번호 재설정 및 로그아웃 API
src/shared/api/auth.ts
checkEmailDuplicate, checkContactDuplicate 함수로 이메일/연락처 중복 확인. createPasswordResetSession으로 Firebase 토큰 기반 재설정 세션 생성(sessionId 반환). resetPassword로 새 비밀번호 재설정. logoutSession(scope, isLoggedIn)으로 서버 로그아웃 호출. 모두 axios 에러 시 응답 데이터 기반 메시지/코드 매핑 및 네트워크 고정 메시지 처리.
SMS 인증 훅 (useFindPasswordPhoneVerification)
src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts
Firebase SMS 인증 상태(phone, smsSent, smsCode, verified, sessionId) 관리. sendSms에서 전화번호 정규화(11자리) 및 국제전화 변환 후 Firebase 발송. verifySms에서 코드 검증 및 신선한 Firebase 토큰 확보 후 createPasswordResetSession 호출로 sessionId 생성. 컴포넌트 언마운트 시 재캡차 정리.
비밀번호 찾기 페이지
src/pages/find-password/index.tsx
3단계 조건부 렌더링(step 상태). 1단계: 이메일 입력 및 형식 검증(EMAIL_REGEX), 2단계: PhoneVerification 컴포넌트로 SMS 인증, 3단계: 새 비밀번호 입력 및 재설정. 각 단계별 검증 실패 시 에러 상태 표시. 재설정 성공 시 완료 화면에서 로그인 버튼으로 리다이렉트.
라우팅 및 경로 유틸
src/shared/constants/routes.ts, src/shared/lib/authApiPath.ts, src/app/App.tsx, src/pages/login/index.tsx
ROUTES.AUTH.FIND_PASSWORD 상수(/find-password) 추가. getAuthApiBasePath(scope) 유틸로 scope에 따라 base path(manager/app) 결정. App.tsx에서 MobileRouteLayoutWithoutDocbar 하위에 비밀번호 찾기 라우트 추가. LoginPage의 비밀번호 찾기 링크를 상수로 변경.

인증 인프라 개선

Layer / File(s) Summary
토큰 갱신 및 401 자동 재시도
src/shared/lib/refreshToken.ts, src/shared/lib/axiosInstance.ts
refreshAccessToken() 함수로 리프레시 토큰 사용해 액세스 토큰 재발급 및 스토어(useAuthStore) 갱신. authInstance 응답 인터셉터에 401 처리 추가: _retry 플래그로 무한 재시도 방지, failedQueue 배열로 동시 갱신 시나리오 관리(갱신 중 요청은 큐에 적재 후 완료 시 일괄 재시도). 갱신 실패 시 큐 요청 reject 및 logout() 호출.
로그아웃 서버 세션 처리
src/pages/my/index.tsx
handleLogout을 async로 변경해 logoutSession(scope, isLoggedIn) 호출로 서버 로그아웃 수행. 실패 시 예외 무시하고 finally에서 항상 로컬 세션 정리(logout()) 및 로그인 페이지 리다이렉트 보장.
회원가입 검증 강화
src/pages/signup/hooks/useEmailVerification.ts, src/pages/signup/hooks/usePhoneVerification.ts, src/shared/lib/utils/emailValidation.ts, src/features/auth/ui/PhoneVerification.tsx, src/pages/signup/components/{EmailVerification,Step1UserInfo,Step2AccountInfo}.tsx, src/shared/hooks/index.ts, src/features/auth/index.ts
useEmailVerificationsendCodeisValidEmailFormat(trimmed) 검증 및 checkEmailDuplicate 호출 추가로 형식 및 중복 확인. usePhoneVerificationsendSmscheckContactDuplicate(normalized) 호출로 중복 확인 추가(11자리 길이 검증도 강화). EMAIL_REGEXisValidEmailFormat 유틸 새로 추가. PhoneVerification props를 명시적 PhoneVerificationProps 타입으로 정의. 회원가입 컴포넌트들의 임포트 경로를 @/features/auth 모듈로 통일. useTimer 훅 re-export 추가.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60분

복잡도 분석:

  • 비밀번호 재설정 3단계 플로우, Firebase SMS 인증, 서버 세션 관리의 새로운 도메인 로직
  • 토큰 갱신 인터셉터의 동시성 처리(failedQueue) 및 401 재시도 메커니즘
  • API 계약 변경(이메일/연락처 중복 확인, 로그아웃 시그니처 확장) 및 에러 처리 일관성 검증
  • 회원가입 입력 검증 강화로 여러 파일의 흐름 변경

Suggested reviewers

  • kim3360
  • limtjdghks
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(비밀번호 재설정 페이지 및 토큰 재발급)을 명확하게 반영하며, 변경 범위와 목적을 잘 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿 구조(ID, 변경내용, 구현사항, 구현시연)를 따르며, ALT-231 이슈 추적, 주요 변경(토큰 갱신, 로그아웃, 비밀번호 찾기, 중복 검사, API 경로 매핑)을 상세히 기술하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ALT-231

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/app/App.tsx (1)

15-15: ⚡ Quick win

신규 라우트 페이지도 lazy 로딩으로 맞춰주세요.

FindPasswordPage만 정적 import라 초기 번들에 포함됩니다. SignupPage와 동일하게 lazy + Suspense로 맞추면 라우팅 전략이 일관되고 초기 로드 비용을 줄일 수 있습니다.

As per coding guidelines "src/app/**: 라우팅 구조가 lazy loading을 활용하는지 확인".

Also applies to: 71-74

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/App.tsx` at line 15, FindPasswordPage is statically imported and
should be changed to lazy loading to match SignupPage; replace the static import
of FindPasswordPage with React.lazy (same pattern used for SignupPage), import
Suspense from React (or reuse existing Suspense wrapper) and ensure the route
rendering for FindPasswordPage (and the other routes referenced around the same
block) are wrapped in a Suspense fallback so the component is loaded
asynchronously and removed from the initial bundle; use the same naming and
error boundaries/pattern used by SignupPage to keep routing consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts`:
- Around line 43-51: When the phone number changes, the previous SMS
confirmation object may be reused; update handlePhoneChange to also clear
smsConfirmationRef.current (reset the ref) and any related state, and update
verifySms to guard usage of smsConfirmationRef by first checking smsSent (e.g.,
return/throw if !smsSent) before accessing smsConfirmationRef.current so
previous confirmation contexts cannot be reused; apply the same pattern to the
other phone-change/verify flows referenced around the verifySms handler and the
similar block at lines 86-101.
- Line 14: The hook useFindPasswordPhoneVerification currently imports useTimer
from a pages-level module which creates cross-page coupling; relocate useTimer
into a shared or features layer (e.g., shared/hooks or features/timer) and
update the import in useFindPasswordPhoneVerification to reference the new
shared/features path, ensuring the exported name remains useTimer and that any
tests or usages are updated to the new module; additionally, adjust any barrel
exports if needed so useFindPasswordPhoneVerification imports the stable
shared/features symbol rather than a pages/ submodule.

In `@src/pages/find-password/index.tsx`:
- Line 9: The find-password page directly imports the PhoneVerification
component from the signup page causing an illicit upward-layer dependency;
extract PhoneVerification into a shared feature (e.g., move the component file
to src/features/auth/PhoneVerification or
src/shared/components/PhoneVerification) and export it from that new location,
then update imports in both src/pages/find-password/index.tsx and the signup
page to import from the new shared/features path (ensure the component’s named
export PhoneVerification remains intact and update any related CSS/assets
imports accordingly).

In `@src/shared/api/auth.ts`:
- Around line 462-469: logoutSession currently reads UI state directly via
useAuthStore.getState(), coupling the API layer to the store; change
logoutSession to accept the needed values from callers (e.g., scope and
isLoggedIn) and remove any direct useAuthStore.getState() calls so the function
only performs HTTP work (use getAuthApiBasePath(scope) internally). Update
callers to pass scope (and optionally isLoggedIn) and ensure logoutSession
returns/throws based solely on HTTP results without touching stores or other
layers.

In `@src/shared/lib/axiosInstance.ts`:
- Around line 72-79: The queued requests pushed into failedQueue must mark
originalRequest._retry = true so they don't trigger another refresh after a
failed retry; update the branch inside the isRefreshing block where you create
the new Promise and push to failedQueue so that before returning/creating the
promise you set originalRequest._retry = true (and ensure you also set it again
in the .then handler before calling authInstance) so both the queued item and
the retry path use the _retry flag; reference isRefreshing, failedQueue,
originalRequest, and authInstance when making this change.

---

Nitpick comments:
In `@src/app/App.tsx`:
- Line 15: FindPasswordPage is statically imported and should be changed to lazy
loading to match SignupPage; replace the static import of FindPasswordPage with
React.lazy (same pattern used for SignupPage), import Suspense from React (or
reuse existing Suspense wrapper) and ensure the route rendering for
FindPasswordPage (and the other routes referenced around the same block) are
wrapped in a Suspense fallback so the component is loaded asynchronously and
removed from the initial bundle; use the same naming and error
boundaries/pattern used by SignupPage to keep routing consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b2b6eb03-0970-4dc8-90c1-c5b3b326c2e9

📥 Commits

Reviewing files that changed from the base of the PR and between d07a776 and 5f39d29.

📒 Files selected for processing (13)
  • src/app/App.tsx
  • src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts
  • src/pages/find-password/index.tsx
  • src/pages/login/index.tsx
  • src/pages/my/index.tsx
  • src/pages/signup/components/PhoneVerification.tsx
  • src/pages/signup/hooks/useEmailVerification.ts
  • src/pages/signup/hooks/usePhoneVerification.ts
  • src/shared/api/auth.ts
  • src/shared/constants/routes.ts
  • src/shared/lib/authApiPath.ts
  • src/shared/lib/axiosInstance.ts
  • src/shared/lib/refreshToken.ts

Comment thread src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts Outdated
Comment thread src/pages/find-password/hooks/useFindPasswordPhoneVerification.ts
Comment thread src/pages/find-password/index.tsx Outdated
Comment thread src/shared/api/auth.ts Outdated
Comment thread src/shared/lib/axiosInstance.ts
Comment thread src/pages/find-password/index.tsx Outdated
@dohy-eon dohy-eon merged commit c3c8aa9 into dev May 20, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants