-
Notifications
You must be signed in to change notification settings - Fork 0
홈페이지 리팩토링 #254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
홈페이지 리팩토링 #254
Conversation
…to server component
WalkthroughGameSection 위젯을 제거하고 RSC(GameSection)와 클라이언트 컴포넌트(GameSectionClient)로 분리된 새 구현을 추가했으며, GameCard 관련 import 경로 정리, 홈 페이지 간소화, Playwright 테스트 헬퍼 추가, MSW 초기화 조건 변경, CI env 블록화 및 fetchClient에 ky 기반 훅/에러 처리 도입이 포함됩니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Browser as Browser (Client)
participant HomeRSC as Home Page (RSC)
participant API as getDefaultGame API
participant ClientComp as GameSectionClient
participant Preview as GamePreview Overlay
HomeRSC->>API: getDefaultGame({ cache: "force-cache" })
API-->>HomeRSC: games 데이터 반환
HomeRSC-->>Browser: 섹션 HTML (헤더 + Suspense placeholder)
Browser->>ClientComp: mount with props(games)
ClientComp->>ClientComp: 카드 렌더링 & 이벤트 바인딩
Browser->>ClientComp: 사용자가 카드 클릭
ClientComp->>Preview: useGamePreview → 미리보기 오픈
Preview-->>ClientComp: 미리보기 상태/종료 이벤트
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (2)
service/app/src/app/_components/GameSection/GameSectionClient.tsx (1)
19-19: 불필요한 옵셔널 체이닝Line 19에서
games?.map을 사용하고 있지만,GameSectionClientProps인터페이스에서games는GameListItem[]로 정의되어 있어 non-nullable입니다. 옵셔널 체이닝은 불필요하며,games가 undefined인 경우 TypeScript 타입 시스템이 컴파일 타임에 오류를 발생시켜야 합니다.옵셔널 체이닝을 제거하고
games.map을 사용하는 것이 타입 안정성 측면에서 더 명확합니다.🔎 제안된 수정
- {games?.map((game) => ( + {games.map((game) => (service/app/src/app/_components/GameSection/GameSection.tsx (1)
19-19: className 병합에 cn() 유틸리티 사용 권장템플릿 리터럴로 className을 연결하는 것보다
cn()유틸리티(clsx 또는 tailwind-merge 기반)를 사용하는 것이 더 안전합니다.cn()은 중복 클래스를 제거하고 조건부 클래스를 더 깔끔하게 처리합니다.🔎 제안된 수정
+import { cn } from "@/shared/lib/utils" // 또는 적절한 경로 - className={`flex w-full flex-col items-center justify-center self-stretch p-0 ${className}`} + className={cn("flex w-full flex-col items-center justify-center self-stretch p-0", className)}
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
service/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/_components/HeroSection.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/page.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/ui/GameCard/gameCard.tsxservice/app/src/entities/game/ui/components/index.tsservice/app/src/entities/game/ui/gameCardOptions.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/gameLibrarySkeleton.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/widgets/GameSection.tsx
💤 Files with no reviewable changes (2)
- service/app/src/entities/game/ui/components/index.ts
- service/app/src/widgets/GameSection.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*
📄 CodeRabbit inference engine (CLAUDE.md)
All file names must be camelCase (not PascalCase or kebab-case)
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Component names must use PascalCase in the code (while file names use camelCase)
Use Zustand for client-side state management
Use TanStack Query for server state and API caching
Use async/await for promises instead of .then() chains
Use custom fetch client with interceptors from shared/lib/fetchClient.ts for API requests
**/*.{ts,tsx}: Use TypeScript with ES modules; keep files lower-case kebab or camel per existing folder conventions (e.g.,gameLibraryGrid.tsx)
Favor explicit domain names (e.g.,GameCardOptions,useInfiniteMyGames) and colocate UI, API, and hooks within eachentities/<domain>module
Run ESLint using lint scripts; linting is enforced via lint-staged
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use shared ESLint configuration across all workspaces
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/*.{js,ts,jsx,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Prettier with Tailwind CSS plugin for formatting
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation throughout the codebase
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/*.{ts,tsx,css,json,md}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting using
yarn workspace <pkg> format; this is enforced via lint-staged
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/src/app/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
In the Next.js app workspace, UI routes live in
src/app
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/app/page.tsx
**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Tailwind CSS utilities should be ordered via the Prettier Tailwind plugin; avoid inline style objects unless necessary
Files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/_components/GameSection/GameSectionSkeleton.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/_components/GameSection/GameSection.tsxservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
**/src/entities/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
In the Next.js app workspace, place feature logic under
src/entitiesand colocate Vitest specs in feature folders
Files:
service/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/entities/game/ui/gamePreview.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/*.{ts,tsx} : Favor explicit domain names (e.g., `GameCardOptions`, `useInfiniteMyGames`) and colocate UI, API, and hooks within each `entities/<domain>` module
Applied to files:
service/app/src/app/_components/GameSection/GameSectionHeader.tsxservice/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/app/_components/GameSection/GameSectionClient.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsxservice/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsxservice/app/src/entities/game/hooks/useGamePreview.tsxservice/app/src/app/dashboard/components/dashboardGameSection.tsxservice/app/src/app/__tests__/homePOM.tsservice/app/src/entities/game/ui/gamePreview.tsxservice/app/src/app/page.tsx
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript with ES modules; keep files lower-case kebab or camel per existing folder conventions (e.g., `gameLibraryGrid.tsx`)
Applied to files:
service/app/src/app/games/components/gamesLibrarySection.tsxservice/app/src/entities/game/ui/gameLibraryGrid.tsx
📚 Learning: 2025-11-27T13:45:59.426Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T13:45:59.426Z
Learning: Applies to entities/*/api/**/*.{ts,tsx} : Organize API functions by entity in entities/*/api/
Applied to files:
service/app/src/app/games/components/gamesLibrarySection.tsx
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/src/components/**/*.{ts,tsx} : In `shared/design` package, define reusable UI components in `src/components` and use them in the app workspace instead of redefining widgets
Applied to files:
service/app/src/app/dashboard/components/dashboardGameSection.tsx
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/src/icons/**/*.{ts,tsx} : In `shared/design` package, define reusable icons in `src/icons` and import from this shared package instead of duplicating icon definitions
Applied to files:
service/app/src/app/dashboard/components/dashboardGameSection.tsx
🧬 Code graph analysis (5)
service/app/src/app/_components/GameSection/GameSectionHeader.tsx (1)
shared/design/src/components/button/primaryBoxButton.tsx (1)
PrimaryBoxButton(53-66)
service/app/src/app/_components/GameSection/GameSectionSkeleton.tsx (1)
service/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsx (1)
GameCardSkeleton(1-8)
service/app/src/app/_components/GameSection/GameSectionClient.tsx (2)
service/app/src/entities/game/hooks/useGamePreview.tsx (1)
useGamePreview(17-56)shared/design/src/components/gameCard/index.tsx (1)
GameCard(104-109)
service/app/src/app/_components/GameSection/GameSection.tsx (4)
service/app/src/entities/game/api/getDefaultGame.ts (1)
getDefaultGame(5-10)service/app/src/app/_components/GameSection/GameSectionHeader.tsx (1)
GameSectionHeader(4-15)service/app/src/app/_components/GameSection/GameSectionSkeleton.tsx (1)
GameSectionSkeleton(3-11)service/app/src/app/_components/GameSection/GameSectionClient.tsx (1)
GameSectionClient(11-45)
service/app/src/app/page.tsx (1)
service/app/src/widgets/HomeNavigation.tsx (1)
HomeNavigation(13-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci
🔇 Additional comments (8)
service/app/src/entities/game/ui/gamePreview.tsx (1)
15-15: 임포트 경로 업데이트 확인 완료공유 경로에서 엔티티 기반 경로로
GameCard임포트를 업데이트하여 코딩 가이드라인에 맞게 UI를entities/<domain>모듈 내에 배치했습니다.service/app/src/app/games/components/gamesLibrarySection.tsx (1)
8-9: 임포트 경로 마이그레이션 정상 처리됨
GameCard와GameLibrarySkeleton을 엔티티 기반 경로로 업데이트하여 새로운 프로젝트 구조에 맞게 정리되었습니다.service/app/src/entities/game/ui/gameLibraryGrid.tsx (1)
10-12: 임포트 경로 정상 업데이트됨엔티티 기반 구조에 맞게
GameCard임포트를 업데이트하고, 상대 경로 깊이를 조정하여 리팩토링된 파일 구조를 반영했습니다.service/app/src/entities/game/hooks/useGamePreview.tsx (1)
9-9: 임포트 경로 간소화 확인
GamePreview컴포넌트가ui/디렉토리로 이동하여 경로가 단순화되었습니다.service/app/src/app/__tests__/homePOM.ts (1)
61-63: 테스트 셀렉터 업데이트 정상 반영됨UI 변경에 맞춰 "게임 더 보기" 컨트롤이 버튼에서 링크로 변경된 것을 테스트 셀렉터에 정확히 반영했습니다.
service/app/src/app/dashboard/components/dashboardGameSection.tsx (1)
8-10: 대시보드 컴포넌트 임포트 경로 업데이트 완료게임 관련 UI 컴포넌트들을 엔티티 기반 경로로 일관성 있게 업데이트했습니다.
service/app/src/app/page.tsx (1)
1-13: 홈 페이지 구조 단순화 확인홈 페이지 컴포넌트의 구조 단순화가 일관되게 적용되었습니다:
ErrorBoundary래퍼 제거 (page.tsx, layout.tsx 모두에서)HomeNavigation컴포넌트의isLoggedInprop 제거 (현재className만 수용)- 인증 기반 조건부 로직 완전 제거
- 컴포넌트 임포트 경로 올바르게 업데이트
변경사항이 의도적이며 일관되게 적용되었습니다. 에러 처리는 Next.js의
error.tsx패턴이나 상위Providers컴포넌트 레벨에서 처리되도록 설계되었습니다.service/app/src/app/_components/GameSection/GameSectionClient.tsx (1)
20-42: 구현이 적절합니다게임 카드 렌더링 로직이 올바르게 구현되었습니다. GameCard 컴포지트 컴포넌트 사용, 접근성 속성 추가, 이미지 최적화(placeholder, blur) 등이 적절하게 적용되었습니다.
| import { Suspense } from "react" | ||
|
|
||
| import { getDefaultGame } from "@/entities/game/api/getDefaultGame" | ||
|
|
||
| import { GameSectionClient } from "./GameSectionClient" | ||
| import { GameSectionHeader } from "./GameSectionHeader" | ||
| import { GameSectionSkeleton } from "./GameSectionSkeleton" | ||
|
|
||
| interface GameSectionProps { | ||
| className?: string | ||
| } | ||
|
|
||
| export const GameSection = async ({ className = "" }: GameSectionProps) => { | ||
| const response = await getDefaultGame({ cache: "force-cache" }) | ||
| const games = response.data.games | ||
|
|
||
| return ( | ||
| <section | ||
| className={`flex w-full flex-col items-center justify-center self-stretch p-0 ${className}`} | ||
| > | ||
| <div className="flex min-w-[952px] flex-col gap-28"> | ||
| <GameSectionHeader /> | ||
| <Suspense fallback={<GameSectionSkeleton />}> | ||
| <GameSectionClient games={games} /> | ||
| </Suspense> | ||
| </div> | ||
| </section> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명 규칙 위반
코딩 가이드라인에 따르면 모든 파일명은 camelCase를 사용해야 하지만, 이 파일은 PascalCase(GameSection.tsx)를 사용하고 있습니다. gameSection.tsx로 변경해야 합니다.
코딩 가이드라인 기준
🤖 Prompt for AI Agents
In service/app/src/app/_components/GameSection/GameSection.tsx around lines 1 to
29, the filename uses PascalCase (GameSection.tsx) which violates the project's
camelCase file naming convention; rename the file to gameSection.tsx and update
any imports/exports that reference the old filename (search the repo for
"GameSection" imports and change them to "gameSection"), verify
TypeScript/ESLint build passes, and ensure any path-sensitive references (tests,
storybook, index files) are updated accordingly.
| <Suspense fallback={<GameSectionSkeleton />}> | ||
| <GameSectionClient games={games} /> | ||
| </Suspense> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suspense 경계가 효과가 없습니다
Line 14에서 getDefaultGame을 호출하고 await한 후, 이미 해결된 데이터를 Line 24에서 GameSectionClient에 props로 전달하고 있습니다. GameSectionClient는 클라이언트 컴포넌트이며 이미 사용 가능한 데이터를 렌더링하기만 하므로 suspend되지 않습니다.
Suspense는 비동기 작업이 진행 중일 때만 fallback을 표시합니다. 현재 구조에서는 데이터가 이미 fetching 완료된 후이므로 GameSectionSkeleton이 표시되지 않습니다.
다음 중 하나를 선택하세요:
- 데이터 fetching을 별도의 서버 컴포넌트로 분리하고 해당 컴포넌트를 Suspense로 감싸기
- Suspense를 제거하고 로딩 상태를 다른 방식으로 처리하기
🔎 제안된 수정 (옵션 1: 데이터 fetching 분리)
별도의 서버 컴포넌트를 생성:
// GameSectionContent.tsx
import { getDefaultGame } from "@/entities/game/api/getDefaultGame"
import { GameSectionClient } from "./GameSectionClient"
export const GameSectionContent = async () => {
const response = await getDefaultGame({ cache: "force-cache" })
const games = response.data.games
return <GameSectionClient games={games} />
}그런 다음 GameSection에서 사용:
-export const GameSection = async ({ className = "" }: GameSectionProps) => {
- const response = await getDefaultGame({ cache: "force-cache" })
- const games = response.data.games
-
+export const GameSection = ({ className = "" }: GameSectionProps) => {
return (
<section
className={`flex w-full flex-col items-center justify-center self-stretch p-0 ${className}`}
>
<div className="flex min-w-[952px] flex-col gap-28">
<GameSectionHeader />
<Suspense fallback={<GameSectionSkeleton />}>
- <GameSectionClient games={games} />
+ <GameSectionContent />
</Suspense>
</div>
</section>
)
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In service/app/src/app/_components/GameSection/GameSection.tsx around lines 23
to 25 (and noting getDefaultGame is awaited at line 14), the Suspense boundary
is ineffective because the data is already fetched and passed into the client
component; either move the data fetching into a separate async server component
and render the client inside Suspense, or remove the Suspense and handle loading
state another way. To fix, choose one: (A) create a new server component (e.g.,
GameSectionContent) that calls getDefaultGame and returns <GameSectionClient
games={...} />, then keep Suspense around that server component so the fallback
displays during fetch; or (B) delete the Suspense wrapper here and implement
explicit loading handling inside the client component (or via a prop) since the
data is provided synchronously.
| "use client" | ||
|
|
||
| import type { GameListItem } from "@/entities/game" | ||
| import { useGamePreview } from "@/entities/game/hooks/useGamePreview" | ||
| import * as GameCard from "@/entities/game/ui/GameCard/gameCard" | ||
|
|
||
| interface GameSectionClientProps { | ||
| games: GameListItem[] | ||
| } | ||
|
|
||
| export const GameSectionClient = ({ games }: GameSectionClientProps) => { | ||
| const { openPreview } = useGamePreview() | ||
|
|
||
| return ( | ||
| <div | ||
| className="flex items-center justify-between" | ||
| data-testid="game-section-cards" | ||
| > | ||
| {games?.map((game) => ( | ||
| <GameCard.Root | ||
| key={game.gameId} | ||
| className="w-[178px]" | ||
| title={game.gameTitle} | ||
| onClick={() => openPreview(game)} | ||
| aria-label="게임 카드" | ||
| tabIndex={0} | ||
| > | ||
| <GameCard.Image | ||
| src={game.gameThumbnailUrl ?? "/checker.svg"} | ||
| alt={game.gameTitle} | ||
| sizes="178px" | ||
| placeholder="blur" | ||
| blurDataURL="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzI3IiBoZWlnaHQ9IjQ1OSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZTVlN2ViIi8+PC9zdmc+" | ||
| > | ||
| <GameCard.Badge>{game.questionCount}문제</GameCard.Badge> | ||
| {game.isShared && ( | ||
| <GameCard.Badge variant="bottom-left">공유</GameCard.Badge> | ||
| )} | ||
| </GameCard.Image> | ||
| <GameCard.Description>{game.gameTitle}</GameCard.Description> | ||
| </GameCard.Root> | ||
| ))} | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명 규칙 위반
코딩 가이드라인에 따르면 모든 파일명은 camelCase를 사용해야 하지만, 이 파일은 PascalCase(GameSectionClient.tsx)를 사용하고 있습니다. gameSectionClient.tsx로 변경해야 합니다.
코딩 가이드라인 기준
🤖 Prompt for AI Agents
In service/app/src/app/_components/GameSection/GameSectionClient.tsx lines 1-45:
the filename uses PascalCase but your project requires camelCase; rename the
file to gameSectionClient.tsx (use git mv to preserve history), update all
imports and any barrel/index exports that reference GameSectionClient to the new
filename, adjust any export/default names if your linter enforces
filename-export parity, run the TypeScript/ESLint build to find remaining
references and fix them, then commit the rename.
| import { PrimaryBoxButton } from "@ject-5-fe/design/components/button" | ||
| import Link from "next/link" | ||
|
|
||
| export const GameSectionHeader = () => { | ||
| return ( | ||
| <div className="flex w-full items-center justify-between"> | ||
| <h2 className="typography-heading-lg-semibold text-text-interactive-secondary"> | ||
| 어떤 게임으로 시작해 볼까요? | ||
| </h2> | ||
| <PrimaryBoxButton size="md" _style="outline" asChild> | ||
| <Link href="/games">게임 더 보기</Link> | ||
| </PrimaryBoxButton> | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명 규칙 위반
코딩 가이드라인에 따르면 모든 파일명은 camelCase를 사용해야 하지만, 이 파일은 PascalCase(GameSectionHeader.tsx)를 사용하고 있습니다. gameSectionHeader.tsx로 변경해야 합니다.
컴포넌트 구현은 적절합니다. asChild 패턴을 사용한 Link 래핑이 올바르게 적용되었습니다.
코딩 가이드라인 기준
🤖 Prompt for AI Agents
In service/app/src/app/_components/GameSection/GameSectionHeader.tsx lines 1-15,
the file name violates the camelCase rule; rename the file to
gameSectionHeader.tsx and update all references/imports to the new path. Perform
a git mv to preserve history, update any barrel/index exports or test/storybook
imports that reference the old filename, and ensure TypeScript import paths and
Next.js any-case-sensitive environments reflect the change.
| import { GameCardSkeleton } from "@/entities/game/ui/GameCard/GameCardSkeleton" | ||
|
|
||
| export const GameSectionSkeleton = () => { | ||
| return ( | ||
| <div className="flex items-center justify-between"> | ||
| {Array.from({ length: 4 }).map((_, index) => ( | ||
| <GameCardSkeleton key={index} /> | ||
| ))} | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일 이름 규칙 위반
코딩 가이드라인에 따르면 모든 파일 이름은 camelCase를 사용해야 하지만, 이 파일은 PascalCase를 사용하고 있습니다.
- 현재:
GameSectionSkeleton.tsx - 권장:
gameSectionSkeleton.tsx
마찬가지로 디렉토리 이름도 GameSection/이 아닌 gameSection/이어야 합니다. 코드베이스의 다른 파일들(예: gamePreview.tsx, gameLibraryGrid.tsx)은 camelCase 규칙을 따르고 있으므로 일관성을 위해 이 파일도 동일한 규칙을 따라야 합니다.
기준 코딩 가이드라인
코딩 가이드라인 명시 사항:
**/*: All file names must be camelCase (not PascalCase or kebab-case)**/*.{ts,tsx}: Component names must use PascalCase in the code (while file names use camelCase)
🤖 Prompt for AI Agents
In service/app/src/app/_components/GameSection/GameSectionSkeleton.tsx around
lines 1 to 11, the file and containing directory use PascalCase which violates
the camelCase file naming guideline; rename the file to gameSectionSkeleton.tsx
and the directory to gameSection/, keep the exported component name
GameSectionSkeleton (PascalCase) unchanged in the code, and update all import
paths across the codebase to point to the new
./gameSection/gameSectionSkeleton.tsx location (including barrel/index files and
any tests) so no import breaks occur.
| export const GameCardSkeleton = () => { | ||
| return ( | ||
| <div className="flex w-[178px] flex-col items-start gap-[14px]"> | ||
| <div className="size-[178px] animate-pulse rounded-[10px] bg-gray-200" /> | ||
| <div className="h-[46px] w-[178px] animate-pulse rounded bg-gray-200" /> | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명 규칙 위반
코딩 가이드라인에 따르면 모든 파일명은 camelCase를 사용해야 하지만, 이 파일은 PascalCase(GameCardSkeleton.tsx)를 사용하고 있습니다. gameCardSkeleton.tsx로 변경해야 합니다.
컴포넌트 구현 자체는 적절합니다. 스켈레톤 UI가 명확하게 정의되어 있고 Tailwind 유틸리티가 올바르게 사용되었습니다.
코딩 가이드라인 기준
🤖 Prompt for AI Agents
In service/app/src/entities/game/ui/GameCard/GameCardSkeleton.tsx lines 1-8: the
file name uses PascalCase which violates the camelCase filename rule; rename the
file to gameCardSkeleton.tsx and update all imports/exports that reference this
path (including any index/barrel files, tests, storybooks, and build configs) to
the new path, keeping the component identifier GameCardSkeleton unchanged; run a
project-wide search to replace old path references, adjust any relative import
casing, and run tests/linter to verify nothing breaks.
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
1 similar comment
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
service/app/src/app/__tests__/helpers/log.setup.ts (1)
1-25: 파일명 컨벤션 확인 권장코딩 가이드라인에 따르면 모든 파일명은 camelCase를 사용해야 합니다. 현재
log.setup.ts는 점(.)으로 구분되어 있는데, 더 엄격하게 준수하려면logSetup.ts로 변경할 수 있습니다. 다만.setup.ts는 Playwright에서 널리 사용되는 패턴이므로 현재 형태도 허용 가능합니다.선택적 개선 사항: 파일명을 camelCase로 변경
파일명을
log.setup.ts에서logSetup.ts로 변경하여 camelCase 컨벤션을 엄격하게 준수할 수 있습니다.service/app/src/mocks/mswProvider.tsx (1)
21-37: 선택사항: useEffect 로직을 최적화할 수 있습니다.현재 로직은 올바르게 동작하지만 다음과 같은 경미한 개선이 가능합니다:
의존성 배열:
shouldInitMsw는 환경 변수 기반 상수로 런타임에 변경되지 않습니다. ESLint exhaustive-deps 규칙을 만족하지만, 실제로는 effect가 한 번만 실행됩니다.중복 상태 업데이트:
shouldInitMsw가false일 때,isMswReady는 이미true로 초기화되어 있으므로 라인 28의setIsMswReady(true)호출은 불필요합니다.🔎 최적화된 구현 제안
useEffect(() => { const init = async () => { try { if (shouldInitMsw) { const { initMsw } = await import("./index") await initMsw() + setIsMswReady(true) - } - setIsMswReady(true) + } } catch (error) { console.error("Failed to initialize MSW:", error) setIsMswError(true) setIsMswReady(false) } } init() + // shouldInitMsw는 환경 변수 기반으로 런타임에 변경되지 않음 - }, [shouldInitMsw]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [])
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*
📄 CodeRabbit inference engine (CLAUDE.md)
All file names must be camelCase (not PascalCase or kebab-case)
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Component names must use PascalCase in the code (while file names use camelCase)
Use Zustand for client-side state management
Use TanStack Query for server state and API caching
Use async/await for promises instead of .then() chains
Use custom fetch client with interceptors from shared/lib/fetchClient.ts for API requests
**/*.{ts,tsx}: Use TypeScript with ES modules; keep files lower-case kebab or camel per existing folder conventions (e.g.,gameLibraryGrid.tsx)
Favor explicit domain names (e.g.,GameCardOptions,useInfiniteMyGames) and colocate UI, API, and hooks within eachentities/<domain>module
Run ESLint using lint scripts; linting is enforced via lint-staged
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use shared ESLint configuration across all workspaces
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.{js,ts,jsx,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Prettier with Tailwind CSS plugin for formatting
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation throughout the codebase
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.{ts,tsx,css,json,md}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting using
yarn workspace <pkg> format; this is enforced via lint-staged
Files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Tailwind CSS utilities should be ordered via the Prettier Tailwind plugin; avoid inline style objects unless necessary
Files:
service/app/src/mocks/mswProvider.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-27T13:45:59.426Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T13:45:59.426Z
Learning: Applies to **/__tests__/**/*.spec.tsx : Use Playwright for E2E testing
Applied to files:
service/app/src/app/__tests__/helpers/log.setup.ts
📚 Learning: 2025-11-27T13:45:59.426Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T13:45:59.426Z
Learning: Applies to **/*.test.ts : Use Vitest for unit testing with browser mode using Playwright
Applied to files:
service/app/src/app/__tests__/helpers/log.setup.ts
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/src/app/__tests__/**/*.{spec,test}.{ts,tsx} : In the Next.js app workspace, co-locate Playwright specs in `src/app/__tests__`
Applied to files:
service/app/src/app/__tests__/helpers/log.setup.ts
📚 Learning: 2025-11-27T13:45:59.426Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-27T13:45:59.426Z
Learning: Applies to **/*.{test.ts,msw.config.ts} : Use MSW (Mock Service Worker) for API mocking in development and testing
Applied to files:
service/app/src/app/__tests__/helpers/log.setup.tsservice/app/src/mocks/mswProvider.tsx
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Mock network calls with MSW when running `test:msw`; rely on `fetchClient` interceptors for auth/session coverage
Applied to files:
service/app/src/mocks/mswProvider.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci
🔇 Additional comments (3)
service/app/src/app/__tests__/helpers/log.setup.ts (1)
3-25: 브라우저 로깅 설정이 잘 구현되었습니다.Playwright 테스트 디버깅을 위한 브라우저 로그 캡처 기능이 적절하게 구현되었습니다. console, pageerror, requestfailed, response 이벤트를 모두 처리하여 테스트 중 발생하는 문제를 추적하는 데 유용합니다.
service/app/src/mocks/mswProvider.tsx (2)
14-44: MSW 초기화 로직이 올바르게 구현되었습니다.전체적인 구현이 잘 되어 있습니다:
- 환경에 따라 MSW 초기화 여부를 적절히 결정합니다.
isMswReady게이팅을 통해 MSW가 준비될 때까지 children 렌더링을 차단합니다.- 프로덕션 환경에서는 MSW를 건너뛰고 즉시 렌더링합니다.
한 가지 확인사항: MSW 초기화 실패 시 (라인 29-32) children이 전혀 렌더링되지 않습니다. 이것이 의도된 동작인지 확인하세요. 개발/테스트 환경에서는 적절하지만, 이러한 동작이 예상된 것인지 검증이 필요합니다.
Based on learnings, MSW는 개발 및 테스트 환경에서의 API 모킹에 사용되므로, 초기화 실패 시의 동작이 팀의 개발 워크플로우와 일치하는지 확인하세요.
15-16:NEXT_PUBLIC_TEST환경 변수의 용도와 설정 방식을 명확히 하세요.환경 변수
NEXT_PUBLIC_TEST가 코드에서 참조되고 있으나 프로젝트 내 어디에서도 정의되거나 문서화되지 않았습니다. 이 변수가 다음을 충족하는지 확인하세요:
- 언제 설정되는지 (CI/CD, 로컬 개발 환경 등)
- 프로젝트의 테스트 전략과 일치하는지
.env.test,.env.development등의 환경 파일에서 명시적으로 정의되었는지test:msw스크립트 실행 시 올바르게 설정되는지현재
vitest.msw.config.ts에서 이 변수를 설정하지 않고 있으므로, MSW 초기화는NODE_ENV !== "production"조건에만 의존합니다. 이것이 의도한 동작인지 확인하고, 필요시 문서화하거나 리팩토링하세요.
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
|
❌ 테스트 실패 테스트가 실패했습니다. Actions 로그를 확인해주세요. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
service/app/src/app/page.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*
📄 CodeRabbit inference engine (CLAUDE.md)
All file names must be camelCase (not PascalCase or kebab-case)
Files:
service/app/src/app/page.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Component names must use PascalCase in the code (while file names use camelCase)
Use Zustand for client-side state management
Use TanStack Query for server state and API caching
Use async/await for promises instead of .then() chains
Use custom fetch client with interceptors from shared/lib/fetchClient.ts for API requests
**/*.{ts,tsx}: Use TypeScript with ES modules; keep files lower-case kebab or camel per existing folder conventions (e.g.,gameLibraryGrid.tsx)
Favor explicit domain names (e.g.,GameCardOptions,useInfiniteMyGames) and colocate UI, API, and hooks within eachentities/<domain>module
Run ESLint using lint scripts; linting is enforced via lint-staged
Files:
service/app/src/app/page.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use shared ESLint configuration across all workspaces
Files:
service/app/src/app/page.tsx
**/*.{js,ts,jsx,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Prettier with Tailwind CSS plugin for formatting
Files:
service/app/src/app/page.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation throughout the codebase
Files:
service/app/src/app/page.tsx
**/*.{ts,tsx,css,json,md}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting using
yarn workspace <pkg> format; this is enforced via lint-staged
Files:
service/app/src/app/page.tsx
**/src/app/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
In the Next.js app workspace, UI routes live in
src/app
Files:
service/app/src/app/page.tsx
**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Tailwind CSS utilities should be ordered via the Prettier Tailwind plugin; avoid inline style objects unless necessary
Files:
service/app/src/app/page.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-27T13:46:12.950Z
Learnt from: CR
Repo: JECT-Study/JECT-5-FE PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-27T13:46:12.950Z
Learning: Applies to **/*.{ts,tsx} : Favor explicit domain names (e.g., `GameCardOptions`, `useInfiniteMyGames`) and colocate UI, API, and hooks within each `entities/<domain>` module
Applied to files:
service/app/src/app/page.tsx
🧬 Code graph analysis (1)
service/app/src/app/page.tsx (2)
service/app/src/widgets/HomeNavigation.tsx (1)
HomeNavigation(13-21)service/app/src/app/_components/HeroSection.tsx (1)
HeroSection(5-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci
🔇 Additional comments (2)
service/app/src/app/page.tsx (2)
1-2: LGTM! 새로운 컴포넌트 구조에 맞게 import 경로가 업데이트되었습니다.리팩토링된 컴포넌트 구조에 맞춰 GameSection과 HeroSection의 import 경로가
@/app/_components/로 적절히 변경되었습니다.
5-13: 컴포넌트 단순화가 적절하고 에러 핸들링이 올바르게 구성되어 있습니다.Home 컴포넌트의 인증 로직과 ErrorBoundary 제거는 적절한 단순화입니다. 에러 경계 처리는
service/app/src/app/error.tsx의 루트 레벨 에러 바운더리가 담당하고 있으며, 이는 Next.js 13+ 아키텍처에서의 올바른 패턴입니다.
| </ErrorBoundary> | ||
| ) | ||
| } | ||
| export const dynamic = "force-dynamic" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check page.tsx and GameSection for dynamic data fetching requirements
echo "=== Checking page.tsx content ==="
if [ -f "service/app/src/app/page.tsx" ]; then
cat -n "service/app/src/app/page.tsx"
else
echo "File not found"
fi
echo ""
echo "=== Checking GameSection directory ==="
find service/app/src/app/_components -name "*GameSection*" -type f 2>/dev/null | head -20
echo ""
echo "=== Checking GameSection implementation ==="
find service/app/src/app/_components -path "*GameSection*" -type f -name "*.tsx" -o -name "*.ts" 2>/dev/null | head -5Repository: JECT-Study/JECT-5-FE
Length of output: 1268
🏁 Script executed:
#!/bin/bash
# Check GameSection components for dynamic data patterns
echo "=== GameSection.tsx ==="
cat -n "service/app/src/app/_components/GameSection/GameSection.tsx"
echo ""
echo "=== GameSectionClient.tsx ==="
wc -l "service/app/src/app/_components/GameSection/GameSectionClient.tsx"
head -60 "service/app/src/app/_components/GameSection/GameSectionClient.tsx"Repository: JECT-Study/JECT-5-FE
Length of output: 2760
force-dynamic 설정을 재검토하세요 - 현재 구조상 불필요합니다.
페이지에 export const dynamic = "force-dynamic"이 설정되어 있지만, GameSection은 이미 cache: "force-cache"로 데이터를 페칭하고 Suspense 경계로 클라이언트 컴포넌트를 적절히 감싸고 있습니다. page.tsx는 동적 함수(cookies, headers, searchParams)를 직접 사용하지 않으므로 force-dynamic이 필요하지 않습니다.
제안:
force-dynamic제거 - Suspense 경계가 비동기 데이터 처리를 올바르게 관리합니다- 현재 구조는 Partial Prerendering(PPR)에 이상적이므로 정적 쉘은 캐시되고 동적 부분만 스트리밍됩니다
🤖 Prompt for AI Agents
In service/app/src/app/page.tsx around line 15, remove the unnecessary export
const dynamic = "force-dynamic" since this page does not use dynamic functions
(cookies, headers, searchParams) and GameSection already handles data fetching
with cache: "force-cache" wrapped by Suspense; delete that line so the page can
use the default PPR/static shell behavior and confirm dev build/SSR behaves as
expected.
|
Deploy preview for re-creation ready! ✅ Preview Built with commit bf4d7dc. |
📝 설명
홈페이지 구성 컴포넌트를 리팩토링했습니다. navigation 컴포넌트의 경우 모든 페이지를 대상으로 한 번에 리팩토링 진행 예정이라 따로 건드리지 않았습니다.
🛠️ 주요 변경 사항
리뷰 시 고려해야 할 사항
나중에 수정해야 할 부분
현재 구성이 변경되면서 홈페이지가 pre-rendering 대상이 된 것 같은데, 이때 API_URL이 없어서 빌드에서 계속 에러가 남
해결 방법은 두 가지
원래 첫 번째 방법으로 가려고 했으나, 이렇게 하게 될 경우 getGameDetail (msw를 사용함) 와의 충돌이 발생 (mock data는 uuid 형식을 사용하지 않을 뿐더러, uuid를 사용한다고 하더라도 getGameDetail에서는 id가 동일한지를 검사하기 때문에 형식이 동일해도 서버에 저장된 실제 값을 모르면 404) -> ci에서 e2e 테스트가 무조건 터짐
그래서 현재 2안으로 수정해 둔 상태, 근본적인 해결 방법 찾을 필요 있음...
Summary by CodeRabbit
새로운 기능
접근성
리팩토링
버그 수정/안정성
✏️ Tip: You can customize this high-level summary in your review settings.