Skip to content

[FEAT] 프로필 미완료 시 Guard 설정 변경 - #71

Merged
9g-g9 merged 10 commits into
devfrom
feature/profile-guard
Aug 6, 2026
Merged

[FEAT] 프로필 미완료 시 Guard 설정 변경#71
9g-g9 merged 10 commits into
devfrom
feature/profile-guard

Conversation

@9g-g9

@9g-g9 9g-g9 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📋 작업 내용

  • 프로필 미완료 사용자에 대한 Soft UX 가드 (Header 메뉴 숨김 + 보호 라우트 모달)
  • checkAuth에서 프로필 미생성(me 404 등) 시 JWT 힌트로 user를 채워 AuthGate·status 가드가 동작하도록 수정

🔥 변경 사항

프로필 완료 가드

  • ProfileCompletionGuard: 보호 라우트에서 미완료 시 ProfileRequiredModal 표시 (닫기 불가, 생성 경로로 이동)
  • Header: 미완료 시 GNB·SideNav 링크 숨김, 드롭다운에 프로필 생성 및 로그아웃만 표시
  • useProfileCompletionState로 Gate/Guard 공통 상태 관리
  • isProfileIncomplete로 status false / 프로필 없음(404 등) 판별, 그 외 오류는 실패해도 페이지는 보여줌 (404 제외 에러)
  • allowlist: /profile, /mover/profile
  • 공개 페이지(/, /movers 등)는 가드하지 않음

인증·공통

  • useAuthStore.checkAuth: 토큰 있고 me 실패(401/403 제외) 시 resolveAuthUserFromTokenHint로 세션 유지
  • AlertModal: onClose optional 변경

✅ 체크리스트

  • 로컬에서 정상 동작을 확인했습니다.
  • 기존 기능에 영향을 주지 않는지 확인했습니다.
  • 불필요한 console.log를 제거했습니다.
  • lint를 통과했습니다.
  • README 또는 문서를 수정했습니다. (필요 시)
  • API 명세와 일치하는지 확인했습니다.

📷 스크린샷 (선택)

  • 프로필 생성 화면의 HeaderSideNav
image image
  • 프로필 생성 화면이 아닌 화면으로 이동했을 시 Modal
image

💬 To Reviewer

  • 프로필 미생성 시 UI 이동 방식이 적절한지 확인 부탁드립니다.
  • Guard가 (protected)/layoutCustomerAuthGate/MoverAuthGate에 각각 걸려 있는데, 이 구조가 괜찮은지 확인 부탁드립니다.
  • AlertModal 의 onClose 를 optional 로 바꾸었는데 다른 부분에 지장이 없을지 확인 부탁드립니다.
  • 이미지 업로더는 아직 작업 전입니다. 참고 부탁드리겠습니다!

Summary by CodeRabbit

  • 새로운 기능

    • 고객과 이사 사용자의 프로필 완료 여부를 확인하고, 미완료 시 프로필 생성 안내 모달을 제공합니다.
    • 프로필 미완료 상태에서는 관련 내비게이션을 제한하고 프로필 생성 메뉴를 표시합니다.
    • 주요 견적 페이지에 인증 상태 확인 및 로딩 안내를 추가했습니다.
  • 개선 사항

    • 인증 및 프로필 확인 중 일관된 로딩 화면을 제공합니다.
    • 프로필 생성 안내에서 해당 화면으로 바로 이동할 수 있습니다.
    • 인증 복구와 오류 상황의 세션 처리를 안정화했습니다.
    • 닫기 동작 없이도 안내 모달을 사용할 수 있습니다.

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
moving-frontend Ready Ready Preview Aug 6, 2026 1:17am
moving-frontend-p2ol Ready Ready Preview Aug 6, 2026 1:17am

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 50120611-8b75-4e95-9d03-b0b72a32e745

📥 Commits

Reviewing files that changed from the base of the PR and between 8b10fff and dbd79a8.

📒 Files selected for processing (8)
  • src/app/(customer)/(protected)/layout.tsx
  • src/app/(mover)/(protected)/layout.tsx
  • src/components/auth/CustomerAuthGate.tsx
  • src/components/auth/MoverAuthGate.tsx
  • src/components/auth/ProfileCompletionGuard.tsx
  • src/components/common/Header/Header.tsx
  • src/hooks/profile/useProfileCompletionState.ts
  • src/stores/useAuthStore.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/app/(customer)/(protected)/layout.tsx
  • src/hooks/profile/useProfileCompletionState.ts
  • src/app/(mover)/(protected)/layout.tsx
  • src/components/auth/MoverAuthGate.tsx
  • src/stores/useAuthStore.ts
  • src/components/auth/CustomerAuthGate.tsx
  • src/components/common/Header/Header.tsx

📝 Walkthrough

Walkthrough

인증 게이트와 보호 레이아웃에 ProfileCompletionGuard를 연결했습니다. 프로필 미완료 상태에서는 생성 모달과 제한된 내비게이션을 표시합니다. 견적 페이지에는 인증 게이트와 로딩 메시지를 추가했습니다.

Changes

프로필 완료 검증 기반

Layer / File(s) Summary
프로필 상태 판별
src/hooks/profile/useProfileCompletionState.ts, src/lib/profile/isProfileIncomplete.ts, src/lib/auth/redirect.ts, src/stores/useAuthStore.ts
역할별 프로필 상태와 미완료 조건을 판별합니다. 프로필 생성 경로를 확인합니다. 토큰 기반 인증 복구 처리를 변경했습니다.
프로필 검증과 생성 모달
src/components/auth/ProfileCompletionGuard.tsx, src/components/profile/ProfileRequiredModal.tsx, src/components/common/Modal/AlertModal.tsx, src/stories/AlertModal.stories.tsx
프로필 상태 로딩 중 fallback을 표시합니다. 미완료 상태에서 ProfileRequiredModal을 표시하고 프로필 생성 경로로 이동합니다. AlertModal의 닫기 동작을 선택적으로 변경했습니다.
인증 게이트와 보호 경로 연동
src/components/auth/CustomerAuthGate.tsx, src/components/auth/MoverAuthGate.tsx, src/app/(customer)/(protected)/layout.tsx, src/app/(mover)/(protected)/layout.tsx, src/app/estimate-request/page.tsx, src/app/estimate/received-requests/page.tsx, src/app/estimate/sent/**
고객 및 이사 인증 게이트가 ProfileCompletionGuard를 사용합니다. 보호 레이아웃은 동일한 로딩 fallback을 두 가드에 전달합니다. 견적 페이지는 인증 게이트 내부에서 렌더링됩니다.
미완료 프로필 내비게이션
src/components/common/Header/Header.tsx, src/components/common/Header/HeaderSideNav.tsx, src/components/profile/*Profile*View.tsx
미완료 또는 상태 미확정 프로필에서 내비게이션 링크를 숨깁니다. 안내 문구와 프로필 생성 메뉴를 표시합니다. 관련 프로필 화면의 접근 처리 주석을 갱신했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AuthGate
  participant ProfileCompletionGuard
  participant ProfileRequiredModal
  participant Router
  User->>AuthGate: 보호 페이지 접근
  AuthGate->>ProfileCompletionGuard: 인증된 콘텐츠 전달
  ProfileCompletionGuard->>ProfileRequiredModal: 미완료 프로필 모달 표시
  ProfileRequiredModal->>Router: router.replace(profileCreatePath)
  Router-->>User: 프로필 생성 페이지 표시
Loading

Possibly related PRs

Suggested reviewers: wndnjs2037, yooseohyeon

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 프로필 미완료 사용자를 위한 Guard 추가와 보호 라우트 동작 변경이라는 PR의 주요 내용을 명확하게 요약합니다.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/profile-guard

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/stores/useAuthStore.ts (1)

255-269: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

JWT 힌트 복구 전에 userId를 검증하세요.

userId가 없으면 resolveAuthUserFromTokenHint()id: ""인 사용자를 반환합니다. 그러면 프로필 상태 쿼리가 비활성화되고 ProfileCompletionGuardisStatusPending이 계속 true가 될 수 있습니다. userIdrole이 모두 유효할 때만 힌트 사용자를 복구하고, userId 누락 회귀 테스트를 추가하세요.

🤖 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/stores/useAuthStore.ts` around lines 255 - 269, Validate the result of
resolveAuthUserFromTokenHint before passing it to setAuthenticatedUser in the
token recovery branch. Only restore the hinted user when both userId and role
are present and valid; otherwise continue with the existing fallback state, and
add a regression test covering a missing userId.
🤖 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/app/estimate-request/page.tsx`:
- Around line 1-10: EstimateRequestPage에 페이지별 metadata export를 추가하고, 이 견적 요청 경로에
맞는 제목과 설명을 정의하세요. 기존 CustomerAuthGate 및 렌더링 구조는 변경하지 말고, 프로젝트의 기존 Metadata 타입 또는
메타데이터 작성 관례를 재사용하세요.

In `@src/components/common/Header/Header.tsx`:
- Around line 161-168: Update Header’s profile-navigation gating around
useProfileCompletionState and the related GNB, SideNav, and dropdown rendering
paths. Combine isStatusPending, hasHydrated, and isCheckingAuth into a separate
restricted-state condition, and hide profile links and avoid rendering
completedProfileMenuItems until authentication hydration and profile-status
checks are complete. Preserve the existing incomplete-profile menu behavior once
the state is known.

---

Outside diff comments:
In `@src/stores/useAuthStore.ts`:
- Around line 255-269: Validate the result of resolveAuthUserFromTokenHint
before passing it to setAuthenticatedUser in the token recovery branch. Only
restore the hinted user when both userId and role are present and valid;
otherwise continue with the existing fallback state, and add a regression test
covering a missing userId.
🪄 Autofix

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 Plus

Run ID: c986d8b7-8bf8-4486-9dfc-2fedaca33eeb

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2aead and 5346342.

📒 Files selected for processing (20)
  • src/app/(customer)/(protected)/layout.tsx
  • src/app/(mover)/(protected)/layout.tsx
  • src/app/estimate-request/page.tsx
  • src/app/estimate/received-requests/page.tsx
  • src/app/estimate/sent/[estimateId]/page.tsx
  • src/app/estimate/sent/page.tsx
  • src/components/auth/CustomerAuthGate.tsx
  • src/components/auth/MoverAuthGate.tsx
  • src/components/auth/ProfileCompletionGuard.tsx
  • src/components/common/Header/Header.tsx
  • src/components/common/Header/HeaderSideNav.tsx
  • src/components/common/Modal/AlertModal.tsx
  • src/components/profile/CustomerProfileEditView.tsx
  • src/components/profile/MoverBasicInfoEditView.tsx
  • src/components/profile/MoverProfileEditView.tsx
  • src/components/profile/ProfileRequiredModal.tsx
  • src/hooks/profile/useProfileCompletionState.ts
  • src/lib/auth/redirect.ts
  • src/lib/profile/isProfileIncomplete.ts
  • src/stores/useAuthStore.ts

Comment thread src/app/estimate-request/page.tsx
Comment thread src/components/common/Header/Header.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/hooks/profile/useProfileCompletionState.ts`:
- Around line 41-48: 인증되었지만 역할이 없는 상태를 미확정으로 처리하고 기본 고객용 UI를 렌더링하지 않도록 수정하세요.
src/hooks/profile/useProfileCompletionState.ts의 isAuthPending 및
isCompletionUnresolved 계산에 인증 상태의 빈 role 조건을 포함하세요.
src/components/common/Header/Header.tsx의 resolvedRole 기반 네비게이션과 프로필 메뉴는 역할이 없을 때
숨기거나 로그아웃 메뉴만 표시하도록 변경하고, 고객용 기본값을 사용하지 마세요.
🪄 Autofix

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 Plus

Run ID: 3d22366e-e705-4d39-b82d-206f7ccf0533

📥 Commits

Reviewing files that changed from the base of the PR and between e3dd7d3 and 8b10fff.

📒 Files selected for processing (2)
  • src/components/common/Header/Header.tsx
  • src/hooks/profile/useProfileCompletionState.ts

Comment thread src/hooks/profile/useProfileCompletionState.ts

@juengseulki juengseulki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📋PR 리뷰

👍 좋았던 점

  • 인증 여부와 프로필 완료 여부를 별도 상태로 분리해, 로그인은 완료됐지만 프로필이 없는 사용자를 정상적인 인증 사용자로 유지했습니다.
  • Customer와 Mover의 프로필 상태 조회 및 생성 경로 계산을 useProfileCompletionState로 공통화했습니다.
  • Zustand Hydration, checkAuth, Profile Status 조회가 끝나기 전 상태를 isCompletionUnresolved로 분리해 Header 메뉴 깜빡임을 방지했습니다.
  • isProfileCompleted === false와 프로필 없음 오류만 미완료로 판단하고, 네트워크·5xx 오류에서는 Fail-open 정책을 적용했습니다.
  • 공개 페이지는 그대로 탐색할 수 있게 두고 실제 보호 기능에서만 프로필 생성 안내를 제공해 Soft UX Guard의 목적에 잘 맞았습니다.
  • 고객과 기사 역할별 프로필 생성 경로를 Allowlist로 처리해 생성 화면 자체가 Guard에 막히지 않도록 했습니다.
  • 프로필 미완료 사용자가 보호 기능에 접근했을 때 강제로 이동시키기보다, 접근이 제한된 이유와 프로필 생성 CTA를 모달로 안내했습니다.
  • Header GNB와 SideNav에서도 미완료 상태를 반영해 사용할 수 없는 메뉴를 감추고, 모바일에서는 안내 문구를 제공했습니다.
  • 프로필 완료 여부가 아직 확정되지 않은 상태에서는 완료 사용자 메뉴를 노출하지 않아 초기 렌더링의 잘못된 UI 노출을 방지했습니다.
  • /me가 프로필 미생성으로 실패하더라도 Access Token의 힌트로 사용자 역할과 ID를 복원해 AuthGate 및 Profile Guard가 동작하도록 보완했습니다.
  • 401·403은 기존대로 인증 종료 처리해 실제 인증 실패와 프로필 미생성·일시 오류를 구분했습니다.
  • AlertModal.onClose를 Optional로 변경하면서 닫기 버튼과 Modal 종료 콜백도 함께 조건부 처리해 기존 사용처의 동작을 유지했습니다.

🔍 확인 및 제안

필수 수정사항은 보이지 않았습니다.

프로필 없음 여부를 판별할 때 404와 NOT_FOUND 외에
오류 메시지의 "등록된 프로필" 문자열도 사용하고 있습니다.

현재 백엔드 오류 코드가 완전히 통일되지 않은 상황을 보완하기에는 유용하지만,
향후에는 고객·기사 프로필 없음 전용 Error Code를 추가하고
문자열 의존을 제거하는 것이 더 안전해 보입니다.

또한 ProfileCompletionGuard(protected)/layout
CustomerAuthGate·MoverAuthGate 양쪽에서 사용될 수 있습니다.

현재 구조는 누락 방지에는 안전하지만,
동일한 페이지에서 중복 적용되지 않도록 아래와 같은 기준을 유지하면 좋겠습니다.

  • Route Group 내부 보호 페이지는 (protected)/layout에서 처리
  • Route Group 밖의 개별 보호 페이지는 AuthGate에서 처리

JWT 힌트로 복원한 user는 Client UI와 Guard를 동작시키기 위한 보조 상태로만 사용하고,
실제 권한 검증은 계속 백엔드의 Access Token 및 역할 검증에 맡기는 현재 원칙을 유지하면 충분해 보입니다.

전체적으로 프로필 미완료 상태를 단순 로그아웃이나 강제 Redirect로 처리하지 않고,
공개 탐색은 허용하면서 필요한 기능에만 부드럽게 제한을 거는 흐름이 잘 구성됐습니다.

현재 변경사항 기준으로 병합을 막을 만한 문제는 보이지 않습니다.
수고하셨습니다! 😊


To Reviewer 내용 기준으로 프로필 미생성 시 UI 흐름,
Guard 적용 위치와 AlertModal 변경 영향을 중점적으로 확인했습니다!

프로필 미생성 시 현재 UI 이동 방식은 적절해 보입니다.

공개 페이지는 계속 탐색할 수 있게 하고,
실제 프로필이 필요한 보호 기능에 접근했을 때만
닫을 수 없는 안내 모달과 프로필 생성 CTA를 제공하고 있습니다.

무조건 프로필 생성 페이지로 Redirect하는 방식보다
사용자가 현재 기능을 이용할 수 없는 이유를 이해할 수 있고,
다음 행동도 명확하게 안내받을 수 있어 Soft UX Guard 목적에 잘 맞습니다.

Header와 SideNav에서도 프로필 미완료 상태에 사용할 수 없는 메뉴를 숨기고,
프로필 생성과 로그아웃만 제공하는 흐름도 자연스럽습니다.

추가로 isCompletionUnresolved를 통해
Zustand Hydration, checkAuth, Profile Status 조회가 완료되기 전에는
완료 사용자용 메뉴와 GNB를 노출하지 않도록 처리해
초기 렌더링 시 메뉴가 잠깐 보였다 사라지는 문제도 잘 보완된 것으로 확인했습니다.

Guard를 (protected)/layout
CustomerAuthGate·MoverAuthGate에 각각 둔 구조도 현재 기능상 문제는 없어 보입니다.

React Query가 동일한 Profile Status Query Key를 사용하므로
Guard가 겹치더라도 실제 네트워크 요청은 공유될 가능성이 큽니다.

다만 장기적으로는 다음 기준으로 책임을 구분하면 더 명확할 것 같습니다.

  • (protected) Route Group 내부 페이지는 Layout에서 Profile Guard 적용
  • Route Group 밖에서 AuthGate를 직접 사용하는 페이지는 AuthGate에서 Profile Guard 적용

이 기준을 유지하면 보호 누락을 막으면서도 동일 페이지에 Guard가 중복 적용되는 구조를 줄일 수 있습니다.

AlertModal.onClose를 Optional로 변경한 부분도 적절합니다.

onClose가 전달된 기존 사용처에서는 기존과 동일하게 닫기 버튼과 종료 동작이 유지되고,
onClose가 없는 경우에는 닫기 버튼을 렌더링하지 않으며
하위 Modal에도 닫기 Handler를 전달하지 않습니다.

따라서 기존 모달 동작에 영향을 크게 주지 않으면서,
ProfileRequiredModal처럼 사용자가 닫을 수 없어야 하는 사례를 지원하도록 확장된 형태입니다.

checkAuth에서 /me 실패 시 JWT 힌트로 user를 복원하는 처리도
프로필 미생성 사용자를 로그아웃시키지 않고
AuthGate와 역할별 프로필 생성 흐름을 유지하기 위한 목적에 적절합니다.

다만 JWT 힌트는 Client 화면 상태 복원 용도로만 사용하고,
실제 API 접근 권한은 계속 백엔드 Access Token과 역할 검증에 맡기는 현재 원칙을 유지하면 좋겠습니다.

Comment thread src/lib/profile/isProfileIncomplete.ts
Comment thread src/stores/useAuthStore.ts
Comment thread src/app/(customer)/(protected)/layout.tsx

@yooseohyeon yooseohyeon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

작업하느라 수고하셨습니다! 프로필 미생성 시 가드도 잘 작동하며, 헤더 부분에도 프로필 미등록 시 처리를 구현하신 점이 좋았습니다. 또한 기존 공통 컴포넌트 AlertModal를 활용하신 점도 좋았습니다. onCloseoptional로 바꾸었기 때문에 다른 기존 사용처에 지장이 없을 것으로 보입니다.
프로필 미등록 시 바로 등록 페이지로 이동하거나 프로필 등록을 안내하는 별도의 페이지로 이동하는 대신, 모달을 띄우는 방식은 사용자 입장에서 왜 현재 동작이 막혔는지 알 수 있으면서도 URL·라우트·로딩이 한 번 더 생기는 비효율이 발생하지 않는 이점이 있다고 보았습니다! 현재 정책을 그대로 유지해도 좋을 것 같습니다.

다만 현재 pr 범위엔 살짝 벗어나지만 한 가지 의문이 생겨서 인라인 코멘트로 남겨두었습니다!

Comment thread src/components/auth/ProfileCompletionGuard.tsx
@9g-g9
9g-g9 merged commit f90a74e into dev Aug 6, 2026
4 checks passed
useProfileCompletionState(resolvedRole);

// SSR 로그인 힌트와 status 확정 전: 완료 사용자 메뉴/링크가 깜빡이지 않도록 숨김
const shouldHideNavLinks = isLogin && (isIncomplete || isCompletionUnresolved);

@wndnjs2037 wndnjs2037 Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

프로필이 완료된 사용자도 새로고침 직후에는 GNB와 사이드 링크가 잠깐 비어 보일 수 있을 것 같습니다. isCompletionUnresolved가 hydrate, checkAuth, status 조회가 끝날 때까지 true인데 isLogin은 SSR 힌트 기반이라 첫 페인트부터 true이고, showAuthSkeleton도 우측 프로필 영역만 가리고 있습니다. 링크가 늦게 뜨면서 화면이 밀리지 않는지 한번 확인해보시면 좋을 것 같습니다!

문제가 된다면 드롭다운 메뉴만 확정 후 노출하고 링크는 먼저 보여주거나, 숨기는 대신 스켈레톤으로 자리를 잡아주는 방향이 있을 것 같아요.

Comment on lines +49 to +53
return (
<>
{loadingFallback}
<ProfileRequiredModal open profileCreatePath={profileCreatePath} />
</>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

차단 상태에서 배경으로 loadingFallback을 그대로 쓰고 있는데, AuthGate 경로에서는 이 값이 "견적 요청을 준비하는 중입니다." 같은 로딩 문구라 실제로는 차단인데 준비 중처럼 보일 수 있을 것 같습니다. 차단 시에는 중립 배경이나 모달만 두는 것도 좋을 것 같아요 :)

@wndnjs2037

wndnjs2037 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

개발 고생 많으셨습니다!

useProfileCompletionState로 Header와 Guard가 같은 파생값과 같은 쿼리 키를 공유하는 구조로 짜주셔서 헤더 메뉴 판정과 라우트 차단 판정이 한 곳에서 나오니 서로 어긋날 일이 없고, status 요청도 자연히 공유되어 중복 호출이 줄어드는 장점이 있을 것 같습니다.
isProfileIncomplete도 프로필 없음으로 판별되는 오류만 미완료로 보고 나머지 오류는 fail-open으로 흘려보내는 구조라 서버 일시 오류를 프로필 미완료로 오해해서 사용자를 막아버리는 상황이 생기지 않을 것 같아요.

To Reviewer 답변드리면,

1. 프로필 미생성 시 UI 이동 방식
프로필 미완료는 인증 실패가 아니라 조건 미충족이고, redirect로 처리하면 원래 가려던 경로를 잃고 뒤로가기로 되돌아올 때 다시 튕기는 흐름이 생깁니다. 모달은 URL을 유지하면서 차단 이유와 생성 CTA를 같은 화면에서 보여주니, 이 방식이 적절해 보입니다. 생성 경로를 allowlist로 열어두신 부분도 루프를 막아줘서 잘 맞물려 있는 것 같습니다.

2. layout과 AuthGate 양쪽에 Guard
estimate 페이지들은 모두 (protected) 밖이라 실제로 겹치는 페이지가 없어서 동작상 문제는 없어 보입니다.
다만 중복 방지가 JSDoc 규칙에만 걸려 있으니, 이 페이지들을 (protected) 아래로 옮기고 개별 Gate를 걷어내면 규칙 없이도 Guard가 한 곳에서만 걸리게 처리할 수 있을 것 같습니다.

3. AlertModal onClose optional
필수를 optional로 완화한 변경이라 기존 사용처 영향은 없어 보입니다.
다만 닫을 수 없는 모달을 표현하는 방법이 onClose 생략과 closeDisabled 두 가지가 되어서, 어느 쪽을 기본으로 쓸지 정해두면 좋을 것 같아요!

고생하셨습니다 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants