og 이미지, 메타데이터 추가#267
Conversation
사용자 조사이 변경 사항은 Next.js 애플리케이션에 SEO 및 메타데이터 지원을 추가합니다. 새로운 robots.txt 및 sitemap 생성 모듈을 도입하고, 여러 페이지에 메타데이터를 구성합니다. 변경 사항
예상 코드 리뷰 노력🎯 2 (Simple) | ⏱️ ~12 분 관련 가능성 있는 PR
제안된 레이블
제안된 리뷰어
변경 축하 시
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 1
🧹 Nitpick comments (2)
service/app/src/app/sitemap.ts (1)
1-10: 기본 sitemap 구현은 적절합니다.현재 홈페이지 URL만 포함되어 있습니다. 향후 검색엔진에 노출이 필요한 정적 페이지가 추가되면 sitemap도 함께 확장하는 것을 권장합니다. 동적 게임 페이지는
robots: { index: false }로 설정되어 있으므로 현재 구조는 적절합니다.service/app/src/app/page.tsx (1)
7-41: 메타데이터 구조가 잘 구성되어 있습니다.description과 openGraph.description 간에 표기 차이가 있습니다:
- Line 10: "워크샵"
- Line 26: "워크숍"
일관성을 위해 통일하는 것을 권장합니다.
♻️ 수정 제안
openGraph: { title: "Re:creation - 모두 함께 즐기는 레크레이션", description: - "MT, 워크숍, 소모임에서 바로 사용할 수 있는 라이트 레크리에이션. 인물퀴즈, 명대사퀴즈 등 다양한 게임으로 분위기를 띄워보세요.", + "MT, 워크샵, 소모임에서 바로 사용할 수 있는 라이트 레크리에이션. 인물퀴즈, 명대사퀴즈 등 다양한 게임으로 분위기를 띄워보세요.",
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
service/app/public/og.pngis excluded by!**/*.pngservice/app/public/og/og-16f89e38-b86f-4cb3-b53d-8f0a6a78b8a9.pngis excluded by!**/*.pngservice/app/public/og/og-25cfc8db-4eb1-4f21-8e5b-f4b77189ec2f.pngis excluded by!**/*.pngservice/app/public/og/og-7f9b3c8e-98b2-4cb1-909e-10a7ed3dc7a2.pngis excluded by!**/*.pngservice/app/public/og/og-d108c47d-df0d-4421-a5f0-513fa3d40b47.pngis excluded by!**/*.png
📒 Files selected for processing (5)
service/app/src/app/game/[gameId]/setup/page.tsxservice/app/src/app/layout.tsxservice/app/src/app/page.tsxservice/app/src/app/robots.tsservice/app/src/app/sitemap.ts
🧰 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/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/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/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/page.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use shared ESLint configuration across all workspaces
Files:
service/app/src/app/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/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/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/page.tsx
**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indentation throughout the codebase
Files:
service/app/src/app/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/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/sitemap.tsservice/app/src/app/layout.tsxservice/app/src/app/robots.tsservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/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/layout.tsxservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/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/layout.tsxservice/app/src/app/page.tsxservice/app/src/app/game/[gameId]/setup/page.tsx
🧠 Learnings (2)
📚 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/layout.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} : 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/game/[gameId]/setup/page.tsx
🧬 Code graph analysis (1)
service/app/src/app/page.tsx (1)
service/app/src/app/layout.tsx (1)
metadata(11-20)
⏰ 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 (4)
service/app/src/app/robots.ts (1)
1-13: LGTM!Next.js App Router의
MetadataRoute.Robots패턴을 올바르게 사용하여 robots.txt를 생성하고 있습니다./admin경로를 크롤링에서 제외하는 것은 적절한 설정입니다.service/app/src/app/layout.tsx (1)
11-20: LGTM!
metadataBase설정으로 하위 페이지의 상대 경로 OG 이미지 URL(/og.png,/og/og-{gameId}.png)이 올바르게 절대 경로로 변환됩니다.authors필드도 적절하게 추가되었습니다.service/app/src/app/page.tsx (1)
33-33:/og.png파일이public폴더에 정상 존재합니다.service/app/public 디렉토리에서 og.png 파일을 확인했습니다.
service/app/src/app/game/[gameId]/setup/page.tsx (1)
25-25: OG 이미지는 정적 파일로 public/og/ 디렉토리에 정상 배치되어 있습니다.
/og/og-${params.gameId}.png경로의 이미지들이public/og/디렉토리에 UUID 기반의 게임 ID로 정상 저장되어 있으므로, 현재 구현은 올바릅니다.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| export async function generateMetadata({ | ||
| params, | ||
| }: { | ||
| params: { gameId: string } | ||
| }) { | ||
| const { data: game } = await getGameDetail(params.gameId) | ||
| return { | ||
| title: `${game.gameTitle} - Re:creation`, | ||
| robots: { | ||
| index: false, | ||
| follow: false, | ||
| }, | ||
| openGraph: { | ||
| title: game.gameTitle, | ||
| type: "website", | ||
| locale: "ko_KR", | ||
| images: [ | ||
| { | ||
| url: `/og/og-${params.gameId}.png`, | ||
| width: 1200, | ||
| height: 630, | ||
| alt: game.gameTitle, | ||
| type: "image/png", | ||
| }, | ||
| ], | ||
| }, | ||
| } | ||
| } |
There was a problem hiding this comment.
getGameDetail 실패 시 에러 처리가 필요합니다.
getGameDetail(params.gameId) 호출이 실패할 경우(존재하지 않는 게임, 네트워크 오류 등) 메타데이터 생성이 실패하여 페이지 렌더링에 영향을 줄 수 있습니다. try-catch를 통한 에러 처리 또는 fallback 메타데이터 반환을 권장합니다.
🛡️ 에러 처리 추가 제안
export async function generateMetadata({
params,
}: {
params: { gameId: string }
}) {
- const { data: game } = await getGameDetail(params.gameId)
- return {
- title: `${game.gameTitle} - Re:creation`,
- robots: {
- index: false,
- follow: false,
- },
- openGraph: {
- title: game.gameTitle,
- type: "website",
- locale: "ko_KR",
- images: [
- {
- url: `/og/og-${params.gameId}.png`,
- width: 1200,
- height: 630,
- alt: game.gameTitle,
- type: "image/png",
- },
- ],
- },
+ try {
+ const { data: game } = await getGameDetail(params.gameId)
+ return {
+ title: `${game.gameTitle} - Re:creation`,
+ robots: {
+ index: false,
+ follow: false,
+ },
+ openGraph: {
+ title: game.gameTitle,
+ type: "website",
+ locale: "ko_KR",
+ images: [
+ {
+ url: `/og/og-${params.gameId}.png`,
+ width: 1200,
+ height: 630,
+ alt: game.gameTitle,
+ type: "image/png",
+ },
+ ],
+ },
+ }
+ } catch {
+ return {
+ title: "Re:creation",
+ robots: {
+ index: false,
+ follow: false,
+ },
+ }
}
}|
Deploy preview for re-creation ready! ✅ Preview Built with commit 204b8d8. |
📝 설명
🛠️ 주요 변경 사항
세부 게임 정보 메타데이터 관련 이슈레이징 후 수정 예정
리뷰 시 고려해야 할 사항
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.