perf: 기사님 상세 초기 렌더링 및 CTA 로딩 개선 - #95
Conversation
- 서버 prefetch 상세 데이터를 초기 화면에 사용 - 히어로 프로필 이미지 preload 적용
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthrough무버 상세 페이지가 서버 프리패치 데이터를 초기 화면에 사용합니다. 인증 또는 활성 견적 조회 중에는 액션 스켈레톤을 표시합니다. 프로필 이미지 preload와 리뷰 페이지 prefetch를 추가했습니다. Changes무버 상세 페이지 흐름
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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/components/mover/detail/MoverDetailView.tsx`:
- Around line 118-121: Update the MoverDetailView rendering around
MoverDetailProfile so the favorite UI is hidden or replaced with a skeleton
while isInitialLoading is true; do not pass initialDetail’s guest favorite state
to the rendered FavoriteButton during authentication lookup, while preserving
the existing customer-action visibility after loading completes.
🪄 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
Run ID: be408127-fea3-476f-bebb-8d93392fd2cf
📒 Files selected for processing (5)
src/app/movers/[moverId]/page.tsxsrc/components/common/DetailHeroBanner.tsxsrc/components/mover/detail/MoverDetailActions.tsxsrc/components/mover/detail/MoverDetailView.tsxsrc/hooks/useMoverDesignation.ts
- 리뷰 페이지가 로드된 뒤 300ms 후 다음 페이지 한 장을 자동 prefetch
juengseulki
left a comment
There was a problem hiding this comment.
📋 PR 리뷰
👍 좋았던 점
- 서버에서 prefetch한 기사님 상세 데이터를
initialDetail로 전달해 인증 초기화 중에도 기본 상세 정보를 먼저 렌더링하도록 한 점이 좋았습니다. HydrationBoundary의 캐시만 사용하는 것이 아니라 초기 렌더링에 필요한 상세 데이터를 직접 전달해 LCP 대상 콘텐츠가 빠르게 노출될 수 있도록 구성한 점이 좋았습니다.- 초기에는 서버에서 받은 상세 데이터를 사용하고, 사용자별 Query가 준비되면 기존
queryDetail로 전환하도록 해 기존 TanStack Query 흐름을 유지한 점도 좋았습니다. - 히어로 프로필 이미지에만 선택적으로
preload를 적용해 LCP 개선 대상 외의 이미지까지 불필요하게 우선 로드하지 않도록 한 점이 적절해 보입니다. - 인증 상태뿐 아니라 고객의 활성 견적 요청 조회까지 완료된 뒤 CTA 상태를 확정하도록 해, 스켈레톤 이후 비활성 버튼이 잠깐 노출됐다가 활성화되는 UI 전환을 방지한 점이 좋았습니다.
- 사용자별 찜 상태가 확정되기 전에는 찜 액션을 노출하지 않아 guest 기준 상태가 먼저 보였다가 변경되는 플리커도 방지할 수 있을 것으로 보입니다.
- 데스크톱 CTA 로딩 상태에서도 서버에서 이미 확인된 기사님 이름은 바로 표시하고 버튼 영역만 스켈레톤으로 처리해 불필요한 로딩 UI 범위를 줄인 점이 좋았습니다.
- CTA 스켈레톤이 실제 버튼 영역과 유사한 공간을 확보하도록 구성되어 인증 및 활성 견적 조회 완료 후 발생하는 레이아웃 변화를 줄이는 목적과 잘 맞습니다.
- 현재 리뷰 페이지가 로드된 뒤 300ms 후 다음 페이지를 자동 prefetch하면서 기존 hover/focus prefetch도 유지해, 사용자의 이동 시점에 따라 캐시 또는 진행 중인 요청을 재사용할 수 있도록 한 점이 좋았습니다.
- LCP 측정도 동일한 Slow 4G 환경에서 수정 전/후를 비교해 실제 성능 개선 효과를 함께 확인한 점이 좋았습니다.
🔍 확인 및 제안
1. 초기 guest 상세 → 사용자별 상세 전환
initialDetail은 guest scope의 상세 데이터이고 이후 인증 상태가 확인되면 사용자별 상세 Query 결과로 전환되는 구조로 확인했습니다.
찜이나 CTA처럼 사용자별 상태가 필요한 영역은 Query가 준비되기 전까지 별도로 숨기거나 스켈레톤을 노출하고 있어 guest 상태가 잘못 노출되는 문제는 잘 방지되어 있는 것으로 보입니다.
일반 공개 상세 정보가 guest/authenticated 간 동일하다는 현재 API 기준에서는 적절한 구조로 보입니다.
2. 리뷰 자동 prefetch
현재 페이지가 정상적으로 로드된 뒤 300ms 후 다음 페이지를 자동 prefetch하고 기존 hover/focus prefetch도 유지하는 구조로 확인했습니다.
동일한 query key를 사용하고 있어 이미 캐시가 존재하거나 요청이 진행 중인 경우 TanStack Query에서 이를 재사용할 수 있으므로 현재 구조에서는 적절해 보입니다.
추후 모바일 환경에서 네트워크 요청량을 더욱 엄격하게 관리해야 하는 요구사항이 생긴다면 자동 prefetch 범위를 조정하는 정도는 검토할 수 있을 것 같습니다.
3. isAuthPending 반환값
useMoverDesignation에서 isActionsLoading과 함께 isAuthPending도 반환하도록 변경된 부분이 확인됩니다.
현재 호출부에서 isAuthPending을 별도로 사용하지 않는다면 훅 외부에 노출해야 하는 값인지 한 번 확인해도 좋을 것 같습니다.
내부 isActionsLoading 계산에만 필요하다면 반환값에서는 제외해도 될 것으로 보이며, 기능상 문제는 아니므로 blocker는 아닙니다.
💬 To Reviewer
서버 prefetch 상세 데이터와 기존 TanStack Query의 사용자별 상세 데이터 전환 흐름을 중점적으로 확인했습니다.
초기에는 서버에서 확보한 guest 상세를 initialDetail로 사용하고,
사용자별 Query가 준비되면 기존 queryDetail로 전환하도록 구성되어 있어
LCP 개선을 위한 초기 렌더링과 이후 실제 사용자 상태 반영이 잘 분리되어 있는 것으로 보입니다.
특히 사용자별 상태가 중요한 찜 액션과 CTA는
인증 상태 및 활성 견적 요청 조회가 완료되기 전까지 스켈레톤 또는 비노출 상태로 유지하고 있어,
guest 기준 상태나 임시 비활성 버튼이 먼저 노출되는 문제를 잘 방지한 것으로 확인했습니다.
히어로 프로필 이미지 역시 상세 화면의 LCP 후보 이미지에만 preload를 적용해
다른 이미지까지 불필요하게 우선 로드하지 않은 점이 적절해 보입니다.
리뷰 다음 페이지 prefetch도 현재 페이지 렌더 이후 300ms delayed prefetch와 기존 hover/focus prefetch를 함께 사용하고 있어,
페이지 이동 시 캐시 또는 진행 중인 요청을 재사용할 수 있는 구조로 확인했습니다.
|
page.tsx에서 서버가 prefetch한 상세 데이터를 getQueryData로 꺼내서 initialDetail로 클라이언트에 넘기고, MoverDetailView에서는 인증 확인이 끝나기 전까지 이 initialDetail을 화면에 그리다가 확인이 끝나면 queryDetail로 변경하는 구조로 잘 짜주신 것 같아요. 질문 주신 내용 답변드립니다. 2. 상호작용 있을 때만 하는 게 나은지 3. 페이지 한 개만 prefetch하는 범위가 적절한지 4. 성능 개선 효과 검증용 도구 지표는 LCP만이 아니라 CLS(Cumulative Layout Shift)도 같이 보면 좋을 것 같습니다. 고생 많으셨습니다 👍 |
📋 작업 내용
🔥 변경 사항
src/app/movers/[moverId]/page.tsxDetailHeroBannerpreload를 적용했습니다.MoverDetailView,MoverDetailActions,useMoverDesignationMoverDetailReviews✅ 체크리스트
📷 스크린샷 (선택)
LCP 측정 비교 (5.97s → 1.45s)
동일 조건: 데스크톱 뷰포트, Slow 4G, Disable cache, 로컬에서
build && start수정 전
수정 후
💬 To Reviewer
preload대상으로 제한해 초기 이미지 요청을 앞당겼습니다.멘토님께 드릴 질문
Summary by CodeRabbit