Skip to content

fix: 새로고침 후 기사님 찜 상태가 초기화되는 문제 수정 - #48

Merged
yooseohyeon merged 11 commits into
devfrom
fix/persist-mover-favorites-after-refresh
Aug 1, 2026
Merged

fix: 새로고침 후 기사님 찜 상태가 초기화되는 문제 수정#48
yooseohyeon merged 11 commits into
devfrom
fix/persist-mover-favorites-after-refresh

Conversation

@yooseohyeon

@yooseohyeon yooseohyeon commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📋 작업 내용

새로고침 후 기사님 목록의 찜 상태와 찜한 기사님 목록이 초기화되는 문제를 수정했습니다. 앱 초기 진입 시 인증 상태 복구가 완료된 후 기사님 목록과 찜한 기사님 목록을 조회하도록 요청 순서를 변경했습니다.


🔥 변경 사항

기사님 목록 조회 시점 조정

  • 인증 상태 확인이 완료된 후 기사님 목록 API를 요청하도록 수정
    • Zustand 인증 상태의 hasHydrated, isCheckingAuth, isAuthenticated를 기준으로 목록 조회 시점 제어
    • 인증 상태 hydrate 및 세션 확인이 완료된 경우에만 기사님 목록 쿼리를 실행하도록 enabled 조건 추가
  • 인증 복구 중에는 비회원 목록 대신 로딩 스켈레톤 표시

React Query 캐시 분리

  • 비회원 목록과 로그인 사용자 목록의 캐시 키를 분리했습니다.
    • 로그인 후 서버의 isFavorite 값을 즉시 다시 확인할 수 있도록 로그인 목록의 staleTime0으로 설정했습니다.
    • 비회원 목록은 기존과 동일하게 60초의 staleTime을 유지합니다.
  • 서버에서 prefetch한 비회원 목록이 로그인 사용자 캐시와 섞이지 않도록 수정했습니다.

찜 목록 인증 처리 개선

  • 찜한 기사님 사이드바가 Access Token 존재 여부가 아닌 인증 복구 완료 상태를 기준으로 조회되도록 변경했습니다.
    • 기존 hasAuthSession() 대신 useCustomerAuthReady()isPending, canFetch를 사용

캐시 정합성 보완 (리뷰 반영)

  • 서버 prefetch와 클라이언트 쿼리가 공통 query-key helper를 사용하도록 변경했습니다.
  • 기사님 목록과 찜한 기사님 목록의 Query Key에 userId 기반 인증 scope를 적용해 계정별 캐시를 분리했습니다.
  • 기사님 목록, 찜 목록, 찜 낙관적 업데이트가 동일한 인증 scope를 사용하도록 통일했습니다.
  • 사용자 정보가 없는 경우 Access Token의 userId를 fallback으로 사용하도록 처리했습니다.
  • 인증 상태이지만 사용자 ID를 확인할 수 없는 경우 별도 scope로 분리하고, 사용자 식별이 완료될 때까지 기사님·찜 목록 쿼리를 실행하지 않습니다.
  • 단건 찜 및 일괄 찜 해제의 낙관적 업데이트 범위를 현재 사용자의 캐시로 제한했습니다.

기사 상세 찜 상태 정합성 개선 (리뷰 반영)

  • 기사 상세 캐시를 인증 scope 기준으로 분리하고, 서버 prefetch는 guest scope를 사용하도록 변경했습니다.
  • 인증 복구 및 사용자 식별 완료 후 현재 사용자 기준으로 상세 API를 조회하도록 수정했습니다.
  • 인증 복구 중 비회원 찜 상태가 잠깐 노출되지 않도록 로딩 스켈레톤을 표시합니다.
  • 찜 낙관적 업데이트·rollback·리뷰 작성 후 갱신이 현재 사용자의 상세 캐시만 대상으로 동작하도록 처리했습니다.

인증 및 UI 동작 보완 (리뷰 반영)

  • 인증 완료 후 무한 스크롤 observer가 다시 연결되도록 수정했습니다.
  • 기사 계정에는 고객용 찜 사이드바와 로그인 안내가 표시되지 않도록 처리했습니다.

✅ 체크리스트

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

💬 To Reviewer

  • 인증 복구가 완료되기 전에 optional 목록 API가 비회원 기준으로 호출되지 않는지 확인 부탁드립니다.
  • 게스트와 로그인 사용자의 기사님 목록 캐시를 분리한 방식이 적절한지 확인 부탁드립니다.

Summary by CodeRabbit

버그 수정

  • 인증 상태 확인 전 기사 목록이 잘못 표시되는 문제를 개선했습니다.
  • 게스트와 로그인 사용자의 기사 및 즐겨찾기 목록을 분리했습니다.
  • 로그인 상태가 복구되면 최신 데이터를 자동으로 확인합니다.
  • 인증 확인 중 목록과 즐겨찾기 사이드바에 적절한 로딩 화면을 제공합니다.
  • 사용자 전환 시 이전 세션의 목록 데이터가 남지 않도록 개선했습니다.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Movers와 즐겨찾기 조회가 인증 범위별 React Query 키를 사용합니다. 인증 상태가 준비된 뒤에만 쿼리를 실행합니다. 즐겨찾기 캐시 갱신과 목록 로딩 UI도 인증 상태를 반영합니다.

Changes

Movers 인증 범위 및 조회 흐름

Layer / File(s) Summary
인증 범위 및 쿼리 키 계약
src/lib/constants/queryKeys.ts, src/hooks/useAuthQueryScope.ts
게스트, 미확정, 사용자별 인증 범위를 추가했습니다. Movers와 즐겨찾기 목록 키에 인증 범위를 포함했습니다.
인증 인지형 쿼리
src/app/movers/page.tsx, src/hooks/useMovers.ts, src/hooks/useFavoriteMovers.ts
서버 prefetch와 클라이언트 조회가 인증 범위 키를 사용합니다. 인증 준비가 완료된 뒤 쿼리를 활성화합니다. 인증 사용자의 stale time은 0으로 설정합니다.
즐겨찾기 인증 범위 캐시 갱신
src/hooks/useFavoriteMover.ts, src/hooks/useBulkRemoveFavoriteMovers.ts
쿼리 취소, 캐시 조회, 낙관적 갱신, 롤백 대상을 현재 인증 범위의 캐시로 제한합니다.
Movers 목록 로딩 상태
src/components/mover/MoversList.tsx
인증 hydration 또는 인증 확인 중에는 IntersectionObserver를 설정하지 않습니다. 해당 상태에서는 초기 스켈레톤을 표시합니다.
즐겨찾기 사이드바 인증 상태
src/components/mover/FavoriteMoversSidebar.tsx
useCustomerAuthReady를 사용해 조회와 렌더링을 제어합니다. 인증 대기 중에는 스켈레톤을 표시하고, 인증된 기사 회원에게는 사이드바를 숨깁니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: 9g-g9

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant useAuthQueryScope
  participant ReactQuery
  participant MoversAPI
  Client->>useAuthQueryScope: 인증 상태와 사용자 ID 조회
  useAuthQueryScope-->>Client: 인증 범위와 준비 상태 반환
  Client->>ReactQuery: 인증 범위 쿼리 실행
  ReactQuery->>MoversAPI: Movers 또는 즐겨찾기 목록 요청
  MoversAPI-->>ReactQuery: 목록 데이터 반환
  ReactQuery-->>Client: 인증 범위 캐시와 목록 갱신
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 새로고침 후 찜 상태가 초기화되는 문제를 수정한다는 제목이 변경 사항과 PR 목표를 정확히 설명합니다.
✨ 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 fix/persist-mover-favorites-after-refresh

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: 3

🧹 Nitpick comments (1)
src/hooks/useMovers.ts (1)

17-17: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Movers 인증 범위 키를 하나의 공통 계약으로 관리하세요.

서버 prefetch와 클라이언트 hook이 인증 범위 문자열을 각각 작성합니다. 한쪽의 값이 바뀌면 HydrationBoundary가 동일한 query를 찾지 못하고 중복 요청을 보낼 수 있습니다.

  • src/hooks/useMovers.ts#L17-L17: 인증 범위를 공통 상수 또는 query-key helper에서 가져오세요.
  • src/app/movers/page.tsx#L34-L35: 동일한 helper로 guest prefetch key를 생성하세요.

As per coding guidelines, 매직 스트링과 중복 로직을 지양하고 공통 query-key 계약을 사용해야 합니다.

🤖 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/hooks/useMovers.ts` at line 17, 인증 범위 문자열이 hook과 서버 prefetch에서 중복 정의되지
않도록 공통 query-key 상수 또는 helper를 도입하세요. src/hooks/useMovers.ts 17-17의 authScope를
해당 계약에서 가져오고, src/app/movers/page.tsx 34-35의 guest prefetch key도 동일한 helper로 생성해
HydrationBoundary가 같은 query key를 사용하도록 하세요.

Sources: Coding guidelines, Path instructions

🤖 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/components/mover/FavoriteMoversSidebar.tsx`:
- Around line 80-82: Update FavoriteMoversSidebar around useCustomerAuthReady
and useFavoriteMovers to branch authentication state separately from the isMover
state. Ensure MOVER users do not enable the customer favorites query or receive
the customer login prompt; retain the existing favorites and login behavior for
regular customers based on isAuthenticated and auth readiness.

In `@src/components/mover/MoversList.tsx`:
- Around line 34-36: Update the infinite-scroll observer effect in MoversList to
include isAuthPending in its dependency list and exit while authentication is
pending. This must allow the effect to rerun and reconnect the sentinel observer
when authentication completes, including when the hydrated guest query’s
existing dependencies have not changed.

In `@src/hooks/useMovers.ts`:
- Around line 17-20: Update the queryKey in useMovers to include the
authenticated user’s unique identifier, such as AuthUser.id or token userId, so
Movers caches are isolated per user while preserving the guest behavior. If no
identifier is available, remove the authenticated Movers cache during session
transitions so prior users’ data cannot remain reusable.

---

Nitpick comments:
In `@src/hooks/useMovers.ts`:
- Line 17: 인증 범위 문자열이 hook과 서버 prefetch에서 중복 정의되지 않도록 공통 query-key 상수 또는 helper를
도입하세요. src/hooks/useMovers.ts 17-17의 authScope를 해당 계약에서 가져오고,
src/app/movers/page.tsx 34-35의 guest prefetch key도 동일한 helper로 생성해
HydrationBoundary가 같은 query key를 사용하도록 하세요.
🪄 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 Plus

Run ID: 5af67b1c-497d-407c-a652-7fb2c583691c

📥 Commits

Reviewing files that changed from the base of the PR and between d631b02 and 408b74b.

📒 Files selected for processing (4)
  • src/app/movers/page.tsx
  • src/components/mover/FavoriteMoversSidebar.tsx
  • src/components/mover/MoversList.tsx
  • src/hooks/useMovers.ts

Comment thread src/components/mover/FavoriteMoversSidebar.tsx Outdated
Comment thread src/components/mover/MoversList.tsx
Comment thread src/hooks/useMovers.ts Outdated

@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 리뷰

👍 좋았던 점

  • 인증 상태의 hydrate와 세션 확인이 모두 완료된 이후에만 기사님 목록 API를 호출하도록 요청 순서를 조정했습니다.
  • 인증 복구 중에는 guest 목록 대신 스켈레톤을 표시해 로그인 사용자의 찜 상태가 잠시 초기화되어 보이는 문제를 방지했습니다.
  • 게스트와 로그인 사용자의 Query Key를 분리해 인증 여부에 따라 달라지는 isFavorite 응답이 같은 캐시에 섞이지 않도록 했습니다.
  • 서버 prefetch 결과를 guest 캐시에 명시적으로 저장하고, 로그인 사용자는 별도의 authenticated 캐시를 사용하도록 맞춘 점이 좋았습니다.
  • 로그인 사용자 목록의 staleTime0으로 설정해 인증 복구 직후 서버의 최신 찜 상태를 다시 확인하도록 구성했습니다.
  • 찜한 기사님 사이드바도 Access Token 존재 여부가 아닌 useCustomerAuthReady()를 사용하도록 변경해 만료된 토큰을 로그인 상태로 오인하는 문제를 방지했습니다.
  • 조회 차단과 로딩 UI, 캐시 분리를 함께 적용해 새로고침 시 발생하던 문제를 단순한 재조회가 아니라 인증 흐름 전체에서 해결한 점이 좋았습니다.

🔍 확인 및 제안

인라인 코멘트로 아래 내용을 남겼습니다.

  • 로그인 사용자는 모두 "authenticated"라는 동일한 Query Key scope를 사용하고 있으므로, 로그아웃 후 다른 고객 계정으로 전환할 때 기존 기사님 목록 캐시가 정리되는지 확인 부탁드립니다.
  • 로그아웃 시 React Query 캐시를 제거하고 있다면 현재 구조를 유지해도 괜찮아 보입니다. 그렇지 않다면 사용자 ID를 Query Key에 포함하거나 세션 변경 시 관련 캐시를 제거하는 방법을 고려할 수 있을 것 같습니다.

To Reviewer에 남겨주신 내용도 확인했습니다.

  • 인증 복구 전에는 enabled: false이므로 optional 기사님 목록 API가 비회원 기준으로 먼저 호출되지 않습니다.
  • 서버 prefetch의 guest 캐시와 로그인 사용자의 authenticated 캐시를 분리한 방식도 현재 문제를 해결하는 데 적절해 보입니다.

전체적으로 새로고침 직후 인증 복구와 React Query 조회 순서가 엇갈려 발생하던 찜 상태 초기화 문제를 깔끔하게 해결한 PR이었습니다. 수고하셨습니다! 😊

Comment thread src/hooks/useMovers.ts 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: 2

🤖 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/components/mover/FavoriteMoversSidebar.tsx`:
- Around line 86-89: Update the favorite-movers query flow around
useFavoriteMovers so its finite and infinite query keys include the current user
identifier or session scope. Ensure FavoriteMoversSidebar passes that scope into
the hook, preserving separate cache entries across session changes and
preventing prior-user data from being displayed.

In `@src/hooks/useAuthQueryCacheReset.ts`:
- Around line 23-31: Update the session-key calculation in
useAuthQueryCacheReset to use the same token-derived user ID fallback as
useMovers when authentication is true but user is null, so recovered sessions do
not use the guest key. Prefer sharing or extracting the common session
identifier logic, and add a test covering logout after this
authentication-recovery path to verify queryClient.clear() removes the previous
user’s cache.
🪄 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 Plus

Run ID: c2b99744-8da7-4344-ac65-657be4fb0af9

📥 Commits

Reviewing files that changed from the base of the PR and between 408b74b and 937c9a1.

📒 Files selected for processing (7)
  • src/app/movers/page.tsx
  • src/components/mover/FavoriteMoversSidebar.tsx
  • src/components/mover/MoversList.tsx
  • src/hooks/useAuthQueryCacheReset.ts
  • src/hooks/useMovers.ts
  • src/lib/constants/queryKeys.ts
  • src/providers/AuthProvider.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/movers/page.tsx
  • src/components/mover/MoversList.tsx
  • src/hooks/useMovers.ts

Comment thread src/components/mover/FavoriteMoversSidebar.tsx
Comment thread src/hooks/useAuthQueryCacheReset.ts 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/lib/constants/queryKeys.ts`:
- Around line 5-6: 인증된 세션에서 유효한 사용자 ID가 없을 때 게스트 스코프를 사용하거나 쿼리를 실행하지 않도록 인증 쿼리
스코프를 수정하세요. src/lib/constants/queryKeys.ts:5-6의 getAuthQueryScope는 해당 상태를 guest와
분리하고, src/hooks/useAuthQueryScope.ts:10-14는 사용자 ID가 유효하지 않으면 관련 쿼리를 비활성화하도록 반환값을
조정하세요. 일반 게스트 세션과 유효한 사용자 ID가 있는 인증 세션의 기존 동작은 유지하세요.
🪄 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 Plus

Run ID: b47b66fb-a4a9-4627-a2dc-fa90c52a0bc1

📥 Commits

Reviewing files that changed from the base of the PR and between 937c9a1 and c2e6b57.

📒 Files selected for processing (5)
  • src/app/movers/page.tsx
  • src/hooks/useAuthQueryScope.ts
  • src/hooks/useFavoriteMovers.ts
  • src/hooks/useMovers.ts
  • src/lib/constants/queryKeys.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/movers/page.tsx
  • src/hooks/useMovers.ts

Comment thread src/lib/constants/queryKeys.ts 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/lib/constants/queryKeys.ts`:
- Around line 16-25: src/lib/constants/queryKeys.ts:16-25에서 authScope와 moverId를
포함하는 MoverDetail 캐시 키 helper를 추가하고, src/hooks/useFavoriteMover.ts:97-99의
취소·스냅샷·갱신·롤백이 해당 helper를 사용하도록 변경하세요. 동일한 인증 범위별 키를 useMoverDetail, SSR
prefetch(항상 AUTH_QUERY_GUEST_SCOPE 사용), useCreateReview 무효화에도 적용하고, 기존
QUERY_KEYS.MOVERS.DETAIL(moverId) 직접 사용을 제거하세요.
🪄 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 Plus

Run ID: 135ffb28-e650-49b9-9e6a-520d6582177b

📥 Commits

Reviewing files that changed from the base of the PR and between e4ab871 and 4526896.

📒 Files selected for processing (6)
  • src/hooks/useAuthQueryScope.ts
  • src/hooks/useBulkRemoveFavoriteMovers.ts
  • src/hooks/useFavoriteMover.ts
  • src/hooks/useFavoriteMovers.ts
  • src/hooks/useMovers.ts
  • src/lib/constants/queryKeys.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/hooks/useAuthQueryScope.ts
  • src/hooks/useMovers.ts
  • src/hooks/useFavoriteMovers.ts

Comment thread src/lib/constants/queryKeys.ts
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.

2 participants