Skip to content

og 이미지, 메타데이터 추가#267

Merged
kimnamheeee merged 4 commits into
devfrom
add-metadata
Jan 15, 2026
Merged

og 이미지, 메타데이터 추가#267
kimnamheeee merged 4 commits into
devfrom
add-metadata

Conversation

@kimnamheeee

@kimnamheeee kimnamheeee commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

📝 설명

🛠️ 주요 변경 사항

세부 게임 정보 메타데이터 관련 이슈레이징 후 수정 예정

리뷰 시 고려해야 할 사항

Summary by CodeRabbit

릴리스 노트

  • New Features
    • 게임 페이지 및 홈페이지에 SEO 메타데이터 추가로 검색 엔진 최적화 개선
    • Open Graph 데이터 지원으로 소셜 미디어 공유 미리보기 강화
    • 검색 엔진용 robots 설정 및 동적 사이트맵 자동 생성

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown

사용자 조사

이 변경 사항은 Next.js 애플리케이션에 SEO 및 메타데이터 지원을 추가합니다. 새로운 robots.txt 및 sitemap 생성 모듈을 도입하고, 여러 페이지에 메타데이터를 구성합니다.

변경 사항

집단 / 파일 변경 요약
SEO 및 메타데이터 설정
service/app/src/app/robots.ts, service/app/src/app/sitemap.ts
새로운 모듈 추가: robots 함수는 /admin 경로 제외, sitemap 함수는 사이트 URL 및 lastModified 타임스탬프 반환
루트 레이아웃 메타데이터
service/app/src/app/layout.tsx
메타데이터 구조 변경: title/description에서 authors 및 metadataBase로 재구성
홈페이지 메타데이터
service/app/src/app/page.tsx
새로운 메타데이터 객체 추가: 제목, 설명, 키워드, openGraph, 이미지 등 SEO 데이터 포함
게임 설정 페이지 메타데이터
service/app/src/app/game/[gameId]/setup/page.tsx
새로운 generateMetadata 함수 추가: 게임 상세정보를 동적으로 조회하여 메타데이터 생성 (openGraph 이미지 URL 포함)

예상 코드 리뷰 노력

🎯 2 (Simple) | ⏱️ ~12 분

관련 가능성 있는 PR

제안된 레이블

✨feature, 👩🏻‍💻frontend

제안된 리뷰어

  • whdgur5717

변경 축하 시

🐰 메타데이터 마법이 흘러흘러,
검색 엔진 친구들을 찾아가고,
robots와 sitemap이 손을 잡고,
SEO의 정원에 새 봄이 피어났다네! 🌱✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning 주요 변경 사항 섹션에는 구체적인 내용이 없고, '설명' 섹션도 비어있으며 '리뷰 시 고려해야 할 사항'은 생략되어 있습니다. 설명 섹션에 작업 내용을 요약하고 주요 변경 사항에는 커밋 SHA와 함께 구체적인 변경 내용을 작성해주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 풀 리퀘스트의 주요 변경 사항인 og 이미지와 메타데이터 추가를 명확하게 요약하고 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@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

🧹 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

📥 Commits

Reviewing files that changed from the base of the PR and between 397364a and 204b8d8.

⛔ Files ignored due to path filters (5)
  • service/app/public/og.png is excluded by !**/*.png
  • service/app/public/og/og-16f89e38-b86f-4cb3-b53d-8f0a6a78b8a9.png is excluded by !**/*.png
  • service/app/public/og/og-25cfc8db-4eb1-4f21-8e5b-f4b77189ec2f.png is excluded by !**/*.png
  • service/app/public/og/og-7f9b3c8e-98b2-4cb1-909e-10a7ed3dc7a2.png is excluded by !**/*.png
  • service/app/public/og/og-d108c47d-df0d-4421-a5f0-513fa3d40b47.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • service/app/src/app/game/[gameId]/setup/page.tsx
  • service/app/src/app/layout.tsx
  • service/app/src/app/page.tsx
  • service/app/src/app/robots.ts
  • service/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.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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 each entities/<domain> module
Run ESLint using lint scripts; linting is enforced via lint-staged

Files:

  • service/app/src/app/sitemap.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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.ts
  • service/app/src/app/layout.tsx
  • service/app/src/app/robots.ts
  • service/app/src/app/page.tsx
  • service/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.tsx
  • service/app/src/app/page.tsx
  • service/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.tsx
  • service/app/src/app/page.tsx
  • service/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.

Comment on lines +7 to +34
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",
},
],
},
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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,
+      },
+    }
   }
 }

@github-actions

Copy link
Copy Markdown

Deploy preview for re-creation ready!

✅ Preview
https://re-creation-23n0ljesq-whdgur5717s-projects.vercel.app

Built with commit 204b8d8.
This pull request is being automatically deployed with vercel-action

@kimnamheeee kimnamheeee merged commit 799a9ab into dev Jan 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant