refactor: 아카이브 탭별 데이터 로딩 분리 및 위시 플로우 개선 - #281
Conversation
* style: layout.tsx에서 불필요한 padding 제거 * style: 참여자 프로필 그룹 z-index 순서 수정 * style: 장바구니와 상태 라벨 사이 여백 조정 * style: 캐러셀 슬라이드 크기 비율 85%에서 90%로 변경 * feat: 토너먼트 헤더에서 뒤로가기 버튼 클릭 시 홈으로 이동하도록 수정 * feat: 장바구니 아이템 수 증가 시 알림 토스트 추가
* fix: 위시 복구 요청 폼 필드명 수정 (price → currentPrice) * feat: 위시 삭제 시 성공 토스트 메시지 추가
* fix: Apple OAuth POST 콜백을 올바른 핸들러로 rewrite하는 미들웨어 추가 * fix: Apple OAuth POST 콜백을 proxy.ts에서 올바른 핸들러로 rewrite * fix: 로그인 상태에서 /login 접근 시 /home으로 리다이렉트 * fix: Apple OAuth POST 콜백 rewrite를 307 redirect로 변경 * fix: Apple 콜백 route.ts 디버그 로그 추가 * fix: Apple 콜백 실패 시 에러 정보를 URL 파라미터로 전달 * fix: Apple 콜백 성공 시 307 대신 302로 리다이렉트하여 POST 루프 방지 * fix: Apple 콜백 쿠키 SameSite=Strict → Lax로 변경하여 cross-site 리다이렉트 후 인증 유지 * chore: Apple 콜백 디버그 코드 제거 * fix: 탈퇴 후 무한루프 유발하는 /login → /home 리다이렉트 제거 * fix: 애플 콜백 쿠키 SameSite 변환 코드 제거 (서버에서 Lax로 일괄 변경) * refactor: 애플 콜백 처리 BE 이관으로 FE route.ts 및 proxy Apple POST 감지 코드 제거 * fix: 애플 로그인 redirectUri를 BE 콜백 URL로 변경 * fix: Apple getAuthUrl 호출 시 redirectUri 파라미터 제거 (BE 브릿지 URL 사용) * fix: no-undefined lint 에러 수정 * fix: Apple redirectUri URL 조합 안전하게 수정
* feat: tournament-item-parsed SSE 이벤트 처리 추가 * feat: 토너먼트 아이템 삭제 시 참여자 화면 실시간 갱신 처리 추가 * chore: 토너먼트 조회 30초 폴링 제거 (SSE로 대체)
* feat: 홈에서 담는중, 플레이 상태인 토너먼트 카드만 보여주도록 수정 * refactor: UserProfileGroup에서 게스트 프로필 이미지 그대로 사용하도록 수정 * feat: Tournament Card 제목 클릭 시 토너먼트 준비/진행/결과 페이지로 이동 * fix: 화면 리사이즈 시 웹 스플래시 로고 한쪽으로 치우치는 오류 수정 * fix: QA 통합 — 토너먼트 시작 흐름 모달 / 영수증 캡처 / 초대 마감 보정 (#236) (#243) * fix: 영수증 캡처 시 S3 이미지 CORS 차단 회피 (cacheBust false + force-cache) * fix: 플레이 체험 게스트(CLONE)는 결과 페이지에서 전체 결과 보기 카드 숨김 * fix: 서버 ISO UTC 응답을 Z 떼지 않고 그대로 파싱 (만료됨 오표시 해결) * fix: 초대 마감 시각 picker 가 ISO 8601 UTC 형식으로 전송하도록 변경 * fix: 휠 picker remount 방지 (key 에서 inviteExpiresAt 제거) * chore: consolelog 삭제 * fix: 초대 마감 시 토너먼트 시작 버튼 비활성 처리 * fix: 영수증 캡처 시 상품 사진 누락 (next/image proxy URL 로 same-origin 우회) * feat: 토너먼트 시작 전 부전승 안내 모달 추가 (2의 거듭제곱 아닌 경우) * feat: 담기 시간 종료 시 주최자에게 자동 안내 모달 노출 * feat: 주최자 시작 SSE 신호 감지 → 참여자에게 자동 안내 모달 노출 * refactor: ConfirmStartDialog / ConfirmExitDialog 의 raw button → 공통 Button 컴포넌트 교체 * chore: format * fix: react-hooks/set-state-in-effect lint 에러 해결 (이전 값 state 패턴으로 변경) * style: not-found 페이지 Link 의 cursor-pointer 제거 및 canonical class 정리 * fix: 휠 picker 드래그 직후 click 이벤트가 잘못된 점프를 일으키던 문제 수정 * fix: 모달 시작 버튼 중복 mutation 호출 방지 (isPending 가드 + disabled) * style: 위시에서 가져오기 CTA 영역 그라데이션 디자인 반영 (#245) * style: 위시에서 가져오기 CTA 영역 그라데이션 디자인 반영 * style: 토너먼트 로딩 브라켓 아이콘 그림자 box-shadow로 변경 * style: 하단 바텀 내비 그라디언트 레이어 추가 (#247) * style: 하단 바텀 내비 그라디언트 레이어 추가 * fix: 바텀 내비 그라디언트 포털 SSR 오류 수정 및 lint 에러 해결 * style: 토너먼트 준비 페이지 상태 라벨 주최자·참여자 디자인 통일 (#251) * fix: 화면 확대 시 장바구니 크기 미복구 버그 수정 (#252) * fix: 장바구니 8개 가득 찬 상태에서 아이템 삭제 시 장바구니 사라짐 버그 수정 (#254) * fix: SSE 알림 구독 토큰 만료 시 재연결 처리 (#255) * fix: SSE 알림 구독 토큰 만료 시 재연결 처리 * fix: SSE refresh 하드코딩 URL 상수로 교체 및 웹뷰 토큰 저장 누락 수정 * feat: 위시·토너먼트 아이템 수정 기능 개선 (#256) * feat: 위시 Pending 상태일 때도 클릭 안 되도록 변경 * feat: item status Completed 인 경우에도 클릭 가능하도록 변경 * feat: item status Completed인 경우에 링크 갱신하는 drawer 추가 * feat: 위시, 토너먼트 아이템 Pending 상태일 때도 클릭 안 되도록 변경 * chore: 위시, 토너먼트 아이템 수정 문구 변경 * feat: 위시, 토너먼트 아이템 status = Ready인 경우 이미지 수정 불가능하도록 설정 * feat: 토너먼트 아이템 수정 기능 추가 * style: 토너먼트 아이템 수정 페이지 bg color 고정 * style: 토너먼트 아이템 수정 페이지 bg color 고정 * style: 위시 수정 페이지 스타일 변경 * feat: 링크로 토너먼트 등록 시 에러 토스트 추가 * feat: 토너먼트 아이템 수정 모든 필드 required로 변경 * feat: 위시 수정 모든 필드 required로 변경 * feat: 등록 성공한 위시 갱신 api 연결 * feat: 링크로 위시 등록 시 에러 토스트 추가 * chore: 불필요한 파일 제거 * fix: 토너먼트 아이템에 친구 프로필 얼굴 추가하도록 변경 * fix: 토너먼트 후보 Patch 누락된 에러 핸들링 추가 * refactor: 위시 수정 시 다른 액션 실행되지 않도록 설정 * style: 토너먼트 담기 화면 레이아웃 및 UI 개선 (#259) * style: layout.tsx에서 불필요한 padding 제거 * style: 참여자 프로필 그룹 z-index 순서 수정 * style: 장바구니와 상태 라벨 사이 여백 조정 * style: 캐러셀 슬라이드 크기 비율 85%에서 90%로 변경 * feat: 토너먼트 헤더에서 뒤로가기 버튼 클릭 시 홈으로 이동하도록 수정 * feat: 장바구니 아이템 수 증가 시 알림 토스트 추가 * feat: 위시 상품 삭제 토스트 추가 및 복구 필드명 수정 (#263) * fix: 위시 복구 요청 폼 필드명 수정 (price → currentPrice) * feat: 위시 삭제 시 성공 토스트 메시지 추가 * fix: 애플 로그인 시 비회원으로 로그인되는 문제 수정 (#242) * fix: Apple OAuth POST 콜백을 올바른 핸들러로 rewrite하는 미들웨어 추가 * fix: Apple OAuth POST 콜백을 proxy.ts에서 올바른 핸들러로 rewrite * fix: 로그인 상태에서 /login 접근 시 /home으로 리다이렉트 * fix: Apple OAuth POST 콜백 rewrite를 307 redirect로 변경 * fix: Apple 콜백 route.ts 디버그 로그 추가 * fix: Apple 콜백 실패 시 에러 정보를 URL 파라미터로 전달 * fix: Apple 콜백 성공 시 307 대신 302로 리다이렉트하여 POST 루프 방지 * fix: Apple 콜백 쿠키 SameSite=Strict → Lax로 변경하여 cross-site 리다이렉트 후 인증 유지 * chore: Apple 콜백 디버그 코드 제거 * fix: 탈퇴 후 무한루프 유발하는 /login → /home 리다이렉트 제거 * fix: 애플 콜백 쿠키 SameSite 변환 코드 제거 (서버에서 Lax로 일괄 변경) * refactor: 애플 콜백 처리 BE 이관으로 FE route.ts 및 proxy Apple POST 감지 코드 제거 * fix: 애플 로그인 redirectUri를 BE 콜백 URL로 변경 * fix: Apple getAuthUrl 호출 시 redirectUri 파라미터 제거 (BE 브릿지 URL 사용) * fix: no-undefined lint 에러 수정 * fix: Apple redirectUri URL 조합 안전하게 수정 * fix: 토너먼트 준비 화면 실시간 아이템 상태 미반영 버그 수정 (#264) * feat: tournament-item-parsed SSE 이벤트 처리 추가 * feat: 토너먼트 아이템 삭제 시 참여자 화면 실시간 갱신 처리 추가 * chore: 토너먼트 조회 30초 폴링 제거 (SSE로 대체) * chore: 게스트 프로필 dice bear 처리 삭제 --------- Co-authored-by: 조영찬 <tigerbone@naver.com> Co-authored-by: Soyeong Park <mb535622@gmail.com> Co-authored-by: kanghaeun <145974230+kanghaeun@users.noreply.github.com>
* feat: Firebase Analytics (GA4) 연동 + 핵심 9개 이벤트 로깅 * feat: GA4 web stream 추가 (@next/third-parties) + 환경별 분기 로직 * fix: TOURNAMENT_COMPLETE 이벤트가 tournamentId 변경을 추적하도록 의존성 보강 * fix: firebase 패키지 버전 불일치로 인한 런타임 에러 가능성 제거
* fix: app.json 에 @react-native-firebase/analytics 플러그인 + forceStaticLinking 추가 * feat: GA4 이벤트 시안 기준 보강 (wish_add_start, social_invite_click, guest_visit 추가 + 이벤트명 정리)
* fix: 영수증 상품 사진 미표시 수정 (_next/image 허용 width 사용) * fix: 영수증 상품명 줄바꿈처리
* feat: 담기 마감 모달에 '이어서 담기' 버튼 추가 * feat: 초대 보냈거나 친구 합류한 토너먼트만 담기 타이머 노출
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
More reviews will be available in 23 minutes and 15 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughArchive, Home, Login, MyPage 레이아웃의 React Query 하이드레이션 흐름이 정리되고, 위시/토너먼트 콘텐츠가 서버·클라이언트 분리 구조로 재구성되며, 이미지 로딩 힌트가 ChangesArchive/Home 비차단 prefetch 재편 및 콘텐츠 구조 변경
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (3)
apps/web/src/app/home/_components/tournament-list/client.tsx (1)
7-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winProps 타입명을
TournamentListClientProps로 변경하세요.코딩 가이드라인 및 팀 컨벤션상 컴포넌트 props 타입은
{ComponentName}Props패턴을 따라야 합니다. 일반Props대신TournamentListClientProps를 사용해 주세요.♻️ 제안 변경
-type Props = { +type TournamentListClientProps = { statuses: TournamentStatusT[]; }; -function TournamentListClient({ statuses }: Props) { +function TournamentListClient({ statuses }: TournamentListClientProps) {As per coding guidelines: "Props type names must follow pattern
{ComponentName}Props".🤖 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 `@apps/web/src/app/home/_components/tournament-list/client.tsx` around lines 7 - 9, Rename the generic Props type used by TournamentListClient to TournamentListClientProps to match the component props naming convention. Update the type alias in the TournamentListClient component and any related references so the component’s props follow the {ComponentName}Props pattern consistently.Sources: Coding guidelines, Learnings
apps/web/src/app/mypage/withdraw/layout.tsx (1)
25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value비-MEMBER 리다이렉트 목적지가 archive 레이아웃과 다릅니다.
여기서는
redirect(ROUTES.LOGIN)로 보내지만archive/layout.tsx는getLoginPath(redirectPath)로redirect쿼리를 보존합니다. 일관성을 위해redirectPath를 살리는 방식이 의도된 것인지 확인해 주세요.🤖 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 `@apps/web/src/app/mypage/withdraw/layout.tsx` at line 25, The redirect in the withdraw layout is inconsistent with the archive layout because it drops the intended return path. Update the MEMBER guard in the withdraw layout to use the same login-path flow as archive layout by preserving the current destination via a redirectPath when calling the login redirect helper, and verify the behavior matches the existing getLoginPath(redirectPath) usage rather than redirecting directly to ROUTES.LOGIN.apps/web/src/app/archive/_components/wish-grid/index.tsx (1)
56-61: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value상위 4개 이미지 동시 preload는 LCP에 역효과일 수 있습니다.
Next.js 16에서
preload는<head>에<link rel="preload">를 주입합니다. 여러 이미지를 동시에 preload하면 critical CSS/JS와 대역폭 경쟁이 발생해 오히려 LCP/FCP가 나빠질 수 있습니다. 실제 LCP 후보(보통 1장)에만preload를 적용하고, 나머지 above-the-fold 항목은loading="eager"/fetchPriority="high"로 두는 방식을 검토해 보세요.🤖 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 `@apps/web/src/app/archive/_components/wish-grid/index.tsx` around lines 56 - 61, The WishCard image loading logic in wish-grid/index.tsx currently preloads the first 4 images, which can hurt LCP/FCP by competing with critical resources. Update the mapping logic that sets the WishCard preload prop so only the single likely LCP candidate gets preload, and let other above-the-fold images use eager loading or high fetch priority instead. Keep the fix localized to the WishCard usage in the grid component and adjust any related image props accordingly.
🤖 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 `@apps/web/src/app/archive/_components/wish-content/client.tsx`:
- Around line 27-33: The empty-state path in WishlistList/WishlistTabContent is
rendering a second <main> inside the wrapper <main> in client.tsx. Update
WishlistTabContent’s empty-state container to a non-main element, or keep only
one <main> in the WishlistList tree so the document has a single main landmark.
In `@apps/web/src/app/archive/layout.tsx`:
- Around line 28-33: The archive layout error handling in the catch block only
redirects on 404 and lets other axios failures from getMe fall through, which
can bypass the MEMBER-only guard. Update the catch logic in archive/layout.tsx
to handle non-404 axios errors explicitly: use
isAxiosError<ApiErrorResponseT>(error) to branch, keep the existing 404 redirect
behavior, and for 401/403/500 and other non-404 responses either redirect to the
login path with QUERY_ACTION.VALUE.SESSION_EXPIRED or rethrow so
HydrationBoundary does not proceed on failed auth.
In `@apps/web/src/app/archive/wish/`[id]/_components/ItemEditForm.tsx:
- Line 4: The delete success toast is duplicated between ItemEditForm’s
handleDelete per-call onSuccess and the useDeleteWish hook. Update handleDelete
to only call deleteWishMutation() without passing a per-call onSuccess, and
remove the unused toast import from ItemEditForm so the success toast is shown
only inside useDeleteWish.
In `@apps/web/src/app/archive/wish/`[id]/page.tsx:
- Around line 36-39: The catch block in the archive wish page only handles the
404 case, so 403 responses still fall through to throw and can hit the error
screen. Update the error handling in the page component’s catch path to preserve
the existing 403 routing behavior alongside the 404 redirect, using the same
redirect logic already present in this flow. Keep the decision inside the
archive wish page handler so both “not found” and “forbidden” responses are
routed correctly before rethrowing anything else.
In `@apps/web/src/app/mypage/withdraw/layout.tsx`:
- Around line 26-31: The catch block in MyPageMemberOnlyLayout only handles
Axios 404s, so other Axios errors are swallowed and can still allow children to
render before auth is confirmed. Update the error handling in the layout logic
around isAxiosError and redirect/getLoginPath so that non-404 Axios errors also
trigger the same fallback behavior as archive/layout.tsx, instead of being
ignored.
In `@apps/web/src/utils/queryClient.ts`:
- Line 21: The server-side path in getQueryClient currently creates a new cached
wrapper every time by calling cache(makeQueryClient) inline, which prevents
request-local memoization from being shared. Move cache(makeQueryClient) to
module scope in queryClient.ts, reuse that single memoized function inside
getQueryClient, and keep makeQueryClient as the underlying factory so server
requests consistently share the same cache.
---
Nitpick comments:
In `@apps/web/src/app/archive/_components/wish-grid/index.tsx`:
- Around line 56-61: The WishCard image loading logic in wish-grid/index.tsx
currently preloads the first 4 images, which can hurt LCP/FCP by competing with
critical resources. Update the mapping logic that sets the WishCard preload prop
so only the single likely LCP candidate gets preload, and let other
above-the-fold images use eager loading or high fetch priority instead. Keep the
fix localized to the WishCard usage in the grid component and adjust any related
image props accordingly.
In `@apps/web/src/app/home/_components/tournament-list/client.tsx`:
- Around line 7-9: Rename the generic Props type used by TournamentListClient to
TournamentListClientProps to match the component props naming convention. Update
the type alias in the TournamentListClient component and any related references
so the component’s props follow the {ComponentName}Props pattern consistently.
In `@apps/web/src/app/mypage/withdraw/layout.tsx`:
- Line 25: The redirect in the withdraw layout is inconsistent with the archive
layout because it drops the intended return path. Update the MEMBER guard in the
withdraw layout to use the same login-path flow as archive layout by preserving
the current destination via a redirectPath when calling the login redirect
helper, and verify the behavior matches the existing getLoginPath(redirectPath)
usage rather than redirecting directly to ROUTES.LOGIN.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a641890e-6c3a-4576-b462-4620bc6defdc
📒 Files selected for processing (31)
apps/web/src/app/archive/_components/TournamentHistoryContent.tsxapps/web/src/app/archive/_components/TournamentHistoryList.tsxapps/web/src/app/archive/_components/WishCardSkeleton.tsxapps/web/src/app/archive/_components/WishlistContent.tsxapps/web/src/app/archive/_components/WishlistList.tsxapps/web/src/app/archive/_components/WishlistSkeleton.tsxapps/web/src/app/archive/_components/WishlistTabContent.tsxapps/web/src/app/archive/_components/tournament-history-content/client.tsxapps/web/src/app/archive/_components/tournament-history-content/index.tsxapps/web/src/app/archive/_components/wish-content/client.tsxapps/web/src/app/archive/_components/wish-content/index.tsxapps/web/src/app/archive/_components/wish-grid/WishCard.tsxapps/web/src/app/archive/_components/wish-grid/index.tsxapps/web/src/app/archive/layout.tsxapps/web/src/app/archive/page.tsxapps/web/src/app/archive/wish/[id]/_components/ItemEditForm.tsxapps/web/src/app/archive/wish/[id]/page.tsxapps/web/src/app/home/_components/tournament-list/client.tsxapps/web/src/app/home/_components/tournament-list/index.tsxapps/web/src/app/home/page.tsxapps/web/src/app/login/layout.tsxapps/web/src/app/mypage/withdraw/layout.tsxapps/web/src/app/mypage/withdraw/page.tsxapps/web/src/app/tournament/[id]/match/_components/FinalProductCard.tsxapps/web/src/app/tournament/[id]/match/_components/ProductCard.tsxapps/web/src/app/tournament/[id]/result/_components/ReceiptDrawMachine.tsxapps/web/src/components/base-image/index.tsxapps/web/src/components/button/index.tsxapps/web/src/components/user-profile-group/index.tsxapps/web/src/utils/queryClient.tseas.json
💤 Files with no reviewable changes (4)
- apps/web/src/app/archive/_components/WishlistSkeleton.tsx
- eas.json
- apps/web/src/app/archive/_components/TournamentHistoryContent.tsx
- apps/web/src/app/archive/_components/WishlistContent.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/web/src/app/archive/wish/[id]/layout.tsx (1)
12-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win상대 경로 대신
@/*절대 alias를 사용해 주세요.새 파일의 import도 프로젝트 import 규칙에 맞춰 absolute group에 포함하는 편이 좋습니다.
수정 예시
+import { getWish } from '`@/app/archive/wish/`[id]/_apis/getWish'; import { ROUTES } from '`@/consts/route`'; import type { ApiErrorResponseT } from '`@/types/api`'; import { getLoginPath } from '`@/utils/loginRedirect`'; import { parseIdParam } from '`@/utils/parseIdParam`'; import { getQueryClient } from '`@/utils/queryClient`'; - -import { getWish } from './_apis/getWish';As per coding guidelines,
apps/web/src/**/*.{ts,tsx}: Use absolute path alias@/*for imports instead of relative paths.🤖 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 `@apps/web/src/app/archive/wish/`[id]/layout.tsx at line 12, The import in the layout file uses a relative path instead of the project’s required `@/*` absolute alias. Update the `getWish` import in `layout.tsx` to use the absolute import style, and keep it in the absolute import group so it matches the repo’s `apps/web/src/**/*.{ts,tsx}` import convention.Source: Coding guidelines
🤖 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 `@apps/web/src/app/archive/wish/`[id]/layout.tsx:
- Around line 20-22: The archive wish layout is treating a 403 from getWish as
if it should trigger a login redirect, but /archive/** is already protected by
the parent archive layout. Update the redirect handling in layout.tsx so only
404s are routed back to the archive page, and leave 403s to the existing
authorization flow or separate resource-policy handling instead of sending users
to login. Use the getWish and redirectPath logic in the archive/[id]/layout.tsx
path to remove any per-page guest/session assumptions.
---
Nitpick comments:
In `@apps/web/src/app/archive/wish/`[id]/layout.tsx:
- Line 12: The import in the layout file uses a relative path instead of the
project’s required `@/*` absolute alias. Update the `getWish` import in
`layout.tsx` to use the absolute import style, and keep it in the absolute
import group so it matches the repo’s `apps/web/src/**/*.{ts,tsx}` import
convention.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 4b0593fb-5ddb-409a-b7ee-915bdcac9097
📒 Files selected for processing (6)
apps/web/src/app/archive/_components/WishlistTabContent.tsxapps/web/src/app/archive/layout.tsxapps/web/src/app/archive/wish/[id]/layout.tsxapps/web/src/app/archive/wish/[id]/page.tsxapps/web/src/app/mypage/withdraw/layout.tsxapps/web/src/utils/queryClient.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/web/src/app/archive/_components/WishlistTabContent.tsx
- apps/web/src/utils/queryClient.ts
- apps/web/src/app/archive/layout.tsx
- apps/web/src/app/mypage/withdraw/layout.tsx
There was a problem hiding this comment.
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 `@apps/web/src/app/archive/wish/`[id]/_components/ItemEditForm.tsx:
- Around line 141-151: The delete action in ItemEditForm is still enabled during
an in-flight save, which allows PATCH and DELETE to race on the same wish.
Update the Delete button’s disabled/loading gating and the handleDelete path to
also respect isPatchWishPending, alongside the existing isDeleteWishPending and
isPostWishRefreshPending checks, so deletion cannot start while a save is
pending.
In
`@apps/web/src/app/tournament/`[id]/create/_components/tournament-header/TournamentHeader.tsx:
- Line 39: The central `Header` container is receiving `line-clamp-1`, which
conflicts with its existing `flex items-center justify-center` layout in
`TournamentHeader` and `Header`. Move the truncation behavior off the center
wrapper and apply it to the actual title text element instead, or add a
dedicated title slot/class to `Header` for clamping. Update `TournamentHeader`
so the center container only handles layout, while the text node handles the
single-line ellipsis styling.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 23307523-de37-467e-a09e-d27d420577ec
📒 Files selected for processing (8)
apps/app/app/index.tsxapps/web/src/app/archive/wish/[id]/_components/ItemEditForm.tsxapps/web/src/app/tournament/[id]/create/_components/tournament-header/TournamentHeader.tsxapps/web/src/app/tournament/[id]/create/_components/tournament-item-basket/TournamentBasketItem.tsxapps/web/src/app/tournament/[id]/match/_components/FinalProductCard.tsxapps/web/src/app/tournament/[id]/match/_components/ProductCard.tsxapps/web/src/components/base-image/index.tsxapps/web/src/consts/zIndex.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/web/src/app/tournament/[id]/match/_components/ProductCard.tsx
- apps/web/src/app/tournament/[id]/match/_components/FinalProductCard.tsx
- apps/web/src/components/base-image/index.tsx
* feat: 위시 단일 삭제 시 삭제 성공 토스트 추가 * refactor: layout 권한 확인 시 fetchQuery 활용하여 다중 호출되지 않도록 방지 * feat: getMe 404인 경우 login 페이지로 redirect * chore: 아카이브 페이지 props 네이밍 변경 * refactor: prefetch, getQueryState 대신 fetchQuery로 권한 검증 로직 단순화 * style: 토너먼트 담기 화면 레이아웃 및 UI 개선 (#259) * style: layout.tsx에서 불필요한 padding 제거 * style: 참여자 프로필 그룹 z-index 순서 수정 * style: 장바구니와 상태 라벨 사이 여백 조정 * style: 캐러셀 슬라이드 크기 비율 85%에서 90%로 변경 * feat: 토너먼트 헤더에서 뒤로가기 버튼 클릭 시 홈으로 이동하도록 수정 * feat: 장바구니 아이템 수 증가 시 알림 토스트 추가 * feat: 위시 상품 삭제 토스트 추가 및 복구 필드명 수정 (#263) * fix: 위시 복구 요청 폼 필드명 수정 (price → currentPrice) * feat: 위시 삭제 시 성공 토스트 메시지 추가 * fix: 애플 로그인 시 비회원으로 로그인되는 문제 수정 (#242) * fix: Apple OAuth POST 콜백을 올바른 핸들러로 rewrite하는 미들웨어 추가 * fix: Apple OAuth POST 콜백을 proxy.ts에서 올바른 핸들러로 rewrite * fix: 로그인 상태에서 /login 접근 시 /home으로 리다이렉트 * fix: Apple OAuth POST 콜백 rewrite를 307 redirect로 변경 * fix: Apple 콜백 route.ts 디버그 로그 추가 * fix: Apple 콜백 실패 시 에러 정보를 URL 파라미터로 전달 * fix: Apple 콜백 성공 시 307 대신 302로 리다이렉트하여 POST 루프 방지 * fix: Apple 콜백 쿠키 SameSite=Strict → Lax로 변경하여 cross-site 리다이렉트 후 인증 유지 * chore: Apple 콜백 디버그 코드 제거 * fix: 탈퇴 후 무한루프 유발하는 /login → /home 리다이렉트 제거 * fix: 애플 콜백 쿠키 SameSite 변환 코드 제거 (서버에서 Lax로 일괄 변경) * refactor: 애플 콜백 처리 BE 이관으로 FE route.ts 및 proxy Apple POST 감지 코드 제거 * fix: 애플 로그인 redirectUri를 BE 콜백 URL로 변경 * fix: Apple getAuthUrl 호출 시 redirectUri 파라미터 제거 (BE 브릿지 URL 사용) * fix: no-undefined lint 에러 수정 * fix: Apple redirectUri URL 조합 안전하게 수정 * fix: 토너먼트 준비 화면 실시간 아이템 상태 미반영 버그 수정 (#264) * feat: tournament-item-parsed SSE 이벤트 처리 추가 * feat: 토너먼트 아이템 삭제 시 참여자 화면 실시간 갱신 처리 추가 * chore: 토너먼트 조회 30초 폴링 제거 (SSE로 대체) * style: 홈 토너먼트 목록 및 프로필 이미지 개선 (#265) * feat: 홈에서 담는중, 플레이 상태인 토너먼트 카드만 보여주도록 수정 * refactor: UserProfileGroup에서 게스트 프로필 이미지 그대로 사용하도록 수정 * feat: Tournament Card 제목 클릭 시 토너먼트 준비/진행/결과 페이지로 이동 * fix: 화면 리사이즈 시 웹 스플래시 로고 한쪽으로 치우치는 오류 수정 * fix: QA 통합 — 토너먼트 시작 흐름 모달 / 영수증 캡처 / 초대 마감 보정 (#236) (#243) * fix: 영수증 캡처 시 S3 이미지 CORS 차단 회피 (cacheBust false + force-cache) * fix: 플레이 체험 게스트(CLONE)는 결과 페이지에서 전체 결과 보기 카드 숨김 * fix: 서버 ISO UTC 응답을 Z 떼지 않고 그대로 파싱 (만료됨 오표시 해결) * fix: 초대 마감 시각 picker 가 ISO 8601 UTC 형식으로 전송하도록 변경 * fix: 휠 picker remount 방지 (key 에서 inviteExpiresAt 제거) * chore: consolelog 삭제 * fix: 초대 마감 시 토너먼트 시작 버튼 비활성 처리 * fix: 영수증 캡처 시 상품 사진 누락 (next/image proxy URL 로 same-origin 우회) * feat: 토너먼트 시작 전 부전승 안내 모달 추가 (2의 거듭제곱 아닌 경우) * feat: 담기 시간 종료 시 주최자에게 자동 안내 모달 노출 * feat: 주최자 시작 SSE 신호 감지 → 참여자에게 자동 안내 모달 노출 * refactor: ConfirmStartDialog / ConfirmExitDialog 의 raw button → 공통 Button 컴포넌트 교체 * chore: format * fix: react-hooks/set-state-in-effect lint 에러 해결 (이전 값 state 패턴으로 변경) * style: not-found 페이지 Link 의 cursor-pointer 제거 및 canonical class 정리 * fix: 휠 picker 드래그 직후 click 이벤트가 잘못된 점프를 일으키던 문제 수정 * fix: 모달 시작 버튼 중복 mutation 호출 방지 (isPending 가드 + disabled) * style: 위시에서 가져오기 CTA 영역 그라데이션 디자인 반영 (#245) * style: 위시에서 가져오기 CTA 영역 그라데이션 디자인 반영 * style: 토너먼트 로딩 브라켓 아이콘 그림자 box-shadow로 변경 * style: 하단 바텀 내비 그라디언트 레이어 추가 (#247) * style: 하단 바텀 내비 그라디언트 레이어 추가 * fix: 바텀 내비 그라디언트 포털 SSR 오류 수정 및 lint 에러 해결 * style: 토너먼트 준비 페이지 상태 라벨 주최자·참여자 디자인 통일 (#251) * fix: 화면 확대 시 장바구니 크기 미복구 버그 수정 (#252) * fix: 장바구니 8개 가득 찬 상태에서 아이템 삭제 시 장바구니 사라짐 버그 수정 (#254) * fix: SSE 알림 구독 토큰 만료 시 재연결 처리 (#255) * fix: SSE 알림 구독 토큰 만료 시 재연결 처리 * fix: SSE refresh 하드코딩 URL 상수로 교체 및 웹뷰 토큰 저장 누락 수정 * feat: 위시·토너먼트 아이템 수정 기능 개선 (#256) * feat: 위시 Pending 상태일 때도 클릭 안 되도록 변경 * feat: item status Completed 인 경우에도 클릭 가능하도록 변경 * feat: item status Completed인 경우에 링크 갱신하는 drawer 추가 * feat: 위시, 토너먼트 아이템 Pending 상태일 때도 클릭 안 되도록 변경 * chore: 위시, 토너먼트 아이템 수정 문구 변경 * feat: 위시, 토너먼트 아이템 status = Ready인 경우 이미지 수정 불가능하도록 설정 * feat: 토너먼트 아이템 수정 기능 추가 * style: 토너먼트 아이템 수정 페이지 bg color 고정 * style: 토너먼트 아이템 수정 페이지 bg color 고정 * style: 위시 수정 페이지 스타일 변경 * feat: 링크로 토너먼트 등록 시 에러 토스트 추가 * feat: 토너먼트 아이템 수정 모든 필드 required로 변경 * feat: 위시 수정 모든 필드 required로 변경 * feat: 등록 성공한 위시 갱신 api 연결 * feat: 링크로 위시 등록 시 에러 토스트 추가 * chore: 불필요한 파일 제거 * fix: 토너먼트 아이템에 친구 프로필 얼굴 추가하도록 변경 * fix: 토너먼트 후보 Patch 누락된 에러 핸들링 추가 * refactor: 위시 수정 시 다른 액션 실행되지 않도록 설정 * style: 토너먼트 담기 화면 레이아웃 및 UI 개선 (#259) * style: layout.tsx에서 불필요한 padding 제거 * style: 참여자 프로필 그룹 z-index 순서 수정 * style: 장바구니와 상태 라벨 사이 여백 조정 * style: 캐러셀 슬라이드 크기 비율 85%에서 90%로 변경 * feat: 토너먼트 헤더에서 뒤로가기 버튼 클릭 시 홈으로 이동하도록 수정 * feat: 장바구니 아이템 수 증가 시 알림 토스트 추가 * feat: 위시 상품 삭제 토스트 추가 및 복구 필드명 수정 (#263) * fix: 위시 복구 요청 폼 필드명 수정 (price → currentPrice) * feat: 위시 삭제 시 성공 토스트 메시지 추가 * fix: 애플 로그인 시 비회원으로 로그인되는 문제 수정 (#242) * fix: Apple OAuth POST 콜백을 올바른 핸들러로 rewrite하는 미들웨어 추가 * fix: Apple OAuth POST 콜백을 proxy.ts에서 올바른 핸들러로 rewrite * fix: 로그인 상태에서 /login 접근 시 /home으로 리다이렉트 * fix: Apple OAuth POST 콜백 rewrite를 307 redirect로 변경 * fix: Apple 콜백 route.ts 디버그 로그 추가 * fix: Apple 콜백 실패 시 에러 정보를 URL 파라미터로 전달 * fix: Apple 콜백 성공 시 307 대신 302로 리다이렉트하여 POST 루프 방지 * fix: Apple 콜백 쿠키 SameSite=Strict → Lax로 변경하여 cross-site 리다이렉트 후 인증 유지 * chore: Apple 콜백 디버그 코드 제거 * fix: 탈퇴 후 무한루프 유발하는 /login → /home 리다이렉트 제거 * fix: 애플 콜백 쿠키 SameSite 변환 코드 제거 (서버에서 Lax로 일괄 변경) * refactor: 애플 콜백 처리 BE 이관으로 FE route.ts 및 proxy Apple POST 감지 코드 제거 * fix: 애플 로그인 redirectUri를 BE 콜백 URL로 변경 * fix: Apple getAuthUrl 호출 시 redirectUri 파라미터 제거 (BE 브릿지 URL 사용) * fix: no-undefined lint 에러 수정 * fix: Apple redirectUri URL 조합 안전하게 수정 * fix: 토너먼트 준비 화면 실시간 아이템 상태 미반영 버그 수정 (#264) * feat: tournament-item-parsed SSE 이벤트 처리 추가 * feat: 토너먼트 아이템 삭제 시 참여자 화면 실시간 갱신 처리 추가 * chore: 토너먼트 조회 30초 폴링 제거 (SSE로 대체) * chore: 게스트 프로필 dice bear 처리 삭제 --------- Co-authored-by: 조영찬 <tigerbone@naver.com> Co-authored-by: Soyeong Park <mb535622@gmail.com> Co-authored-by: kanghaeun <145974230+kanghaeun@users.noreply.github.com> * feat: Firebase Analytics 연동 (앱 사용자 행동 분석) (#258) * feat: Firebase Analytics (GA4) 연동 + 핵심 9개 이벤트 로깅 * feat: GA4 web stream 추가 (@next/third-parties) + 환경별 분기 로직 * fix: TOURNAMENT_COMPLETE 이벤트가 tournamentId 변경을 추적하도록 의존성 보강 * fix: firebase 패키지 버전 불일치로 인한 런타임 에러 가능성 제거 * feat: GA4 funnel 이벤트 보강 + iOS Analytics 빌드 fix (#268) * fix: app.json 에 @react-native-firebase/analytics 플러그인 + forceStaticLinking 추가 * feat: GA4 이벤트 시안 기준 보강 (wish_add_start, social_invite_click, guest_visit 추가 + 이벤트명 정리) * fix: 영수증 화면 상품 사진 미표시 및 긴 상품명 넘침 수정 (#271) * fix: 영수증 상품 사진 미표시 수정 (_next/image 허용 width 사용) * fix: 영수증 상품명 줄바꿈처리 * feat: 담기 마감 동작 개선 (협업 의도 판정 + 이어서 담기) (#272) * feat: 담기 마감 모달에 '이어서 담기' 버튼 추가 * feat: 초대 보냈거나 친구 합류한 토너먼트만 담기 타이머 노출 * fix: refresh_token 동시 호출로 인한 자동 로그아웃 수정 (rotation 대응 dedupe) (#273) * fix: SSE 의 refresh 가 별도 경로로 호출되어 race 발생하던 문제 수정 (#274) * refactor: 홈 페이지 단위 await 제거 후 tournamentList 범위에만 await 설정 * refactor: WishCard 이미지 로딩 시 Skeleton 사용 * fix: BaseImage loading -> success로 전환되는 시점에 아무것도 뜨지 않는 현상 해결 * refactor: Archive 페이지 초기 페이지 진입 속도 개선 * refactor: UserProfile image 로딩 시 skeleton 적용 * chore: fix import error * chore: 불필요한 eas 파일 삭제 * perf: wishcard 이미지 preload 최적화 및 LCP 지표 개선 * refactor: queryClient 캐싱 추가 * refactor: Button Spinner dynamic import 로 변경 * refactor: query client 캐시 스코프 변경 * chore: 아카이브/위시 - main 태그 하나만 사용하도록 변경 * fix: 아카이브, 마이페이지 처리되지 않은 에러는 throw되도록 처리 * chore: 위시 삭제 토스트 중복 제거 * refactor: 위시 수정 - layout으로 페이지 진입 권한 확인 분리 * fix: 토너먼트 Pick 뱃지 이미지보다 뒤에 뜨는 현상 제거 * fix: 토너먼트 준비 페이지 헤더 center text 잘림 현상 해결 * fix: 등록 실패한 위시도 삭제 가능하도록 버튼 추가 * fix: 앱 KeyboardAvoidingView 제거 * fix: 프로필 이미지 zindex 수정 * chore: 아카이브 페이지 main 태그 한개로 유지 * chore: 불필요한 403 에러 처리 삭제 * style: TournamentCard 텍스트 줄바꿈되는 경우 대응 * refactor: 위시 저장/삭제/수정 동시에 일어날 수 없도록 disabled 처리 --------- Co-authored-by: kanghaeun <145974230+kanghaeun@users.noreply.github.com> Co-authored-by: Soyeong Park <mb535622@gmail.com> Co-authored-by: 조영찬 <tigerbone@naver.com>
요약
아카이브 진입 시 활성 탭과 무관하게 위시·토너먼트 기록을 모두 prefetch하던 구조를 탭 단위 컴포넌트로 분리해, 보고 있는 탭의 데이터만 서버에서 가져오도록 변경했습니다. 홈도 토너먼트 목록 범위로만 await를 두어 첫 화면 TTFB를 줄였고, 이미지 로딩 중 빈 화면이 보이던 문제를 skeleton으로 처리했습니다. layout·상세 페이지의 권한 검증은
fetchQuery로 단순화해getMe중복 호출을 방지했습니다.변경 사항
1. 아카이브 — 탭별 데이터 로딩 분리
archive/page.tsx에서 활성 탭과 관계없이 위시 infinite query + 토너먼트 목록 prefetch를 모두 awaitwish-content/,tournament-history-content/(index.tsx+client.tsx)로 분리해 활성 탭만 mount·prefetchWishlistContent/TournamentHistoryContent제거 →WishlistList/TournamentHistoryList+WishCardSkeleton도입WishlistPage→ArchivePage)2. 홈 — 토너먼트 목록 await 범위 축소
home/page.tsx전체가 async이며 진입 시 토너먼트 목록 prefetch를 awaittournament-list/서버 컴포넌트로 분리, 해당 섹션만 prefetch·hydrate3. 이미지 로딩 UX — BaseImage·Skeleton
BaseImageloading → success전환 시점에 아무것도 표시되지 않던 현상 수정WishCard이미지 로딩 시 Skeleton 적용UserProfile이미지 로딩 시 Skeleton 적용4. 권한 검증 — fetchQuery 단순화
prefetch+getQueryState로 권한 검증fetchQuery(['me'])단일 호출로 단순화 (archive/wish/[id]/page.tsx)archive/login/mypage·withdrawlayout에서fetchQuery+HydrationBoundary적용 → layout·page 간getMe중복 호출 방지getMe404 시SESSION_EXPIRED쿼리와 함께 로그인 페이지로 redirect5. 위시 — 삭제 토스트
스크린샷
아카이브 위시 탭 lighthouse LCP 지표 점수를 3차례에 걸쳐 개선했습니다. 이미지 로드와 관련하여 추가 개선이 필요해보입니다.



기존
2026-06-24.3.28.56.mov
개선 이후
2026-06-24.3.28.14.mov
연관 이슈
closes #261
Summary by CodeRabbit