Skip to content

검색 엔진 최적화 작업#25

Merged
Stilllee merged 4 commits intodevelopfrom
feature/seo
Apr 4, 2025
Merged

검색 엔진 최적화 작업#25
Stilllee merged 4 commits intodevelopfrom
feature/seo

Conversation

@Stilllee
Copy link
Owner

@Stilllee Stilllee commented Apr 4, 2025

변경 사항

검색 엔진 최적화를 위한 페이지별 메타데이터 설정


관련 이슈

Summary by CodeRabbit

  • 새로운 기능
    • 모든 페이지에서 SEO 및 소셜 미디어 공유 기능을 강화하기 위해 메타데이터가 업데이트되었습니다.
    • 검색, 레시피 편집/조회, 관리자 로그인 페이지에서 사용자 맞춤 정보를 제공하는 동적 메타데이터 기능이 도입되었습니다.
    • 사이트 설명과 검색 엔진 크롤링 지침이 개선되어 검색 노출과 공유 미리보기 정보가 향상되었습니다.

Stilllee added 4 commits April 4, 2025 19:33
- 루트 레이아웃, 메인, 레시피 작성, 관리자 로그인 페이지
- 검색, 상세, 수정 페이지
@Stilllee Stilllee self-assigned this Apr 4, 2025
@coderabbitai
Copy link

coderabbitai bot commented Apr 4, 2025

Walkthrough

이번 변경사항은 여러 페이지에 SEO 및 소셜 미디어 최적화를 위한 메타데이터 설정을 추가 및 개선하는 것입니다. 일부 페이지에서는 정적 메타데이터 상수(metadata)를 도입하였고, 다른 페이지에서는 검색 파라미터나 API 응답을 기반으로 동적 메타데이터를 반환하는 비동기 함수(generateMetadata)가 추가되었습니다. 또한, 레이아웃 파일의 메타데이터 설명이 업데이트되고, 검색 엔진 최적화를 위한 robots 필드가 추가되었습니다.

Changes

파일 변경 요약
src/app/(with-header)/…/(with-search-bar)/page.tsx, src/app/(with-header)/…/new/page.tsx,
src/app/(with-header)/…/admin/login/page.tsx
정적 메타데이터 상수(metadata) 추가.
/new/page.tsx에서는 RecipeForm의 import 경로도 절대 경로로 수정됨.
src/app/(with-header)/…/search/page.tsx, src/app/(with-header)/…/edit/[id]/page.tsx,
src/app/(with-header)/…/recipe/[id]/page.tsx
검색 파라미터 또는 API 응답 기반으로 동적 메타데이터를 생성하는 비동기 함수(generateMetadata) 추가.
※ 각 페이지마다 적절한 데이터 처리 및 오류 핸들링 적용됨.
src/app/layout.tsx 기존 메타데이터의 description 필드를 더 구체적인 내용으로 업데이트하고, SEO를 위한 robots 필드("index, follow")가 추가됨.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Page
  participant API
  Client->>Page: 페이지 요청 (ID 전달)
  Page->>API: 레시피 데이터 fetch (ID 기반)
  API-->>Page: 응답 (성공/실패)
  alt 성공
      Page->>Client: 구성된 metadata 반환
  else 실패
      Page->>Client: 오류 처리 (404 또는 예외 발생)
  end
Loading
sequenceDiagram
  participant Client
  participant Page
  Client->>Page: 검색 파라미터(q) 전달
  Page->>Client: 동적 metadata 생성 및 반환
Loading
✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Stilllee Stilllee merged commit 5b4fc89 into develop Apr 4, 2025
2 of 3 checks passed
Copy link

@coderabbitai coderabbitai bot left a 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 (5)
src/app/(with-header)/new/page.tsx (1)

19-19: 불필요한 세미콜론 제거 권장

<RecipeForm />; 뒤에 세미콜론이 있습니다. JSX 요소 뒤의 세미콜론은 불필요하므로 제거하는 것이 좋겠습니다.

-      <RecipeForm />;
+      <RecipeForm />
src/app/admin/login/page.tsx (1)

4-12: 관리자 로그인 페이지 메타데이터 개선 제안

관리자 로그인 페이지에 적절한 메타데이터가 추가되었습니다. 다만, 관리자 페이지는 일반적으로 검색 엔진에 노출되지 않는 것이 보안 측면에서 좋습니다. robots: "noindex, nofollow" 속성을 추가하는 것을 권장합니다.

export const metadata: Metadata = {
  title: "관리자 로그인 | 테이스토리지",
  description: "테이스토리지 관리자 로그인 페이지입니다.",
  openGraph: {
    title: "관리자 로그인 | 테이스토리지",
    description: "테이스토리지 관리자 로그인 페이지입니다.",
    images: ["/thumbnail.png"],
  },
+  robots: "noindex, nofollow",
};
src/app/(with-header)/(with-search-bar)/search/page.tsx (1)

29-45: 검색 결과 페이지 메타데이터 구현이 잘 되었습니다.

Next.js의 generateMetadata 기능을 활용하여 동적으로 검색어에 따른 페이지 메타데이터를 생성하는 구현이 잘 되었습니다. 타이틀, 설명 및 OG 태그가 적절하게 설정되어 있어 SEO와 소셜 미디어 공유에 도움이 됩니다.

다만, 검색어(q)가 없는 경우에 대한 처리가 없어 "undefined 검색결과 | 테이스토리지"와 같은 타이틀이 생성될 수 있습니다.

다음과 같이 수정하여 검색어가 없는 경우를 처리하는 것이 좋겠습니다:

export async function generateMetadata({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>;
}): Promise<Metadata> {
  const { q } = await searchParams;
+  const searchQuery = q || '전체';

  return {
-    title: `${q} 검색결과 | 테이스토리지`,
-    description: `${q}로 검색한 레시피 목록입니다.`,
+    title: `${searchQuery} 검색결과 | 테이스토리지`,
+    description: `${searchQuery}로 검색한 레시피 목록입니다.`,
    openGraph: {
-      title: `${q} 검색결과 | 테이스토리지`,
-      description: `${q}로 검색한 레시피 목록입니다.`,
+      title: `${searchQuery} 검색결과 | 테이스토리지`,
+      description: `${searchQuery}로 검색한 레시피 목록입니다.`,
      images: ["/thumbnail.png"],
    },
  };
}
src/app/(with-header)/edit/[id]/page.tsx (1)

6-35: 레시피 수정 페이지 메타데이터 생성 기능 구현

레시피 수정 페이지에 대한 SEO 메타데이터를 동적으로 생성하는 기능이 잘 구현되었습니다. 특히 수정 페이지는 검색 엔진에 노출되지 않도록 robots: "noindex, nofollow" 설정을 추가한 것이 좋은 접근입니다.

다만, 동일한 레시피 데이터를 generateMetadata 함수와 Page 컴포넌트에서 중복해서 불러오고 있습니다. 성능 최적화를 위해 데이터 페칭 로직을 공통 유틸리티 함수로 분리하는 것을 고려해 볼 수 있습니다.

또한, Page 컴포넌트에서는 404 응답을 처리하는 반면 generateMetadata에서는 처리하지 않고 있습니다. 일관된 에러 처리를 위해 다음과 같이 수정하는 것이 좋겠습니다:

export async function generateMetadata({
  params,
}: {
  params: Promise<{ id: string }>;
}): Promise<Metadata> {
  const { id } = await params;
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_API_SERVER_URL}/recipe/${id}`,
    { cache: "force-cache" },
  );

+  if (res.status === 404) return {
+    title: "레시피를 찾을 수 없습니다 | 테이스토리지",
+    description: "요청하신 레시피를 찾을 수 없습니다.",
+    robots: "noindex, nofollow"
+  };

  if (!res.ok) {
    throw new Error(
      `레시피 정보를 가져오지 못했습니다: ${res.status} ${res.statusText}`,
    );
  }

  const recipe: RecipeData = await res.json();

  return {
    title: `${recipe.title} 레시피 수정 | 테이스토리지`,
    description: `${recipe.title} 레시피를 수정해보세요!`,
    openGraph: {
      title: `${recipe.title} 레시피 수정 | 테이스토리지`,
      description: `${recipe.title} 레시피를 수정해보세요!`,
      images: ["/thumbnail.png"],
    },
    robots: "noindex, nofollow",
  };
}
src/app/(with-header)/recipe/[id]/page.tsx (1)

6-34: 레시피 상세 페이지 메타데이터 구현

레시피 상세 페이지의 SEO 메타데이터를 동적으로 생성하는 구현이 전반적으로 잘 되었습니다. 타이틀, 설명 및 OG 태그가 적절하게 설정되어 있습니다.

다만, 앞서 언급한 것과 같이 generateMetadata 함수와 Page 컴포넌트에서 동일한 레시피 데이터를 중복해서
불러오고 있습니다. 또한, Page 컴포넌트에서는 404 응답을 처리하지만 generateMetadata에서는 처리하지 않고 있습니다.

아래와 같이 변경하여 404 응답 처리를 추가하는 것이 좋겠습니다:

export async function generateMetadata({
  params,
}: {
  params: Promise<{ id: string }>;
}): Promise<Metadata> {
  const { id } = await params;
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_API_SERVER_URL}/recipe/${id}`,
    { cache: "force-cache" },
  );

+  if (res.status === 404) return {
+    title: "레시피를 찾을 수 없습니다 | 테이스토리지",
+    description: "요청하신 레시피를 찾을 수 없습니다.",
+  };

  if (!res.ok) {
    throw new Error(
      `레시피 정보를 가져오지 못했습니다: ${res.status} ${res.statusText}`,
    );
  }

  const recipe: RecipeData = await res.json();

  return {
    title: `${recipe.title} | 테이스토리지`,
    description: `${recipe.title} 레시피 정보입니다.`,
    openGraph: {
      title: `${recipe.title} | 테이스토리지`,
      description: `${recipe.title} 레시피 정보입니다.`,
      images: ["/thumbnail.png"],
    },
  };
}

또한, 장기적으로는 레시피에 대한 실제 이미지가 있다면 썸네일 이미지로 활용하는 것을 고려해 보세요:

  openGraph: {
    title: `${recipe.title} | 테이스토리지`,
    description: `${recipe.title} 레시피 정보입니다.`,
-    images: ["/thumbnail.png"],
+    images: [recipe.image || "/thumbnail.png"],
  },
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17b9aa0 and 33c3fb8.

⛔ Files ignored due to path filters (7)
  • public/file-text.svg is excluded by !**/*.svg
  • public/globe.svg is excluded by !**/*.svg
  • public/next.svg is excluded by !**/*.svg
  • public/thumbnail.png is excluded by !**/*.png
  • public/vercel.svg is excluded by !**/*.svg
  • public/window.svg is excluded by !**/*.svg
  • src/app/favicon.ico is excluded by !**/*.ico
📒 Files selected for processing (7)
  • src/app/(with-header)/(with-search-bar)/page.tsx (2 hunks)
  • src/app/(with-header)/(with-search-bar)/search/page.tsx (2 hunks)
  • src/app/(with-header)/edit/[id]/page.tsx (1 hunks)
  • src/app/(with-header)/new/page.tsx (1 hunks)
  • src/app/(with-header)/recipe/[id]/page.tsx (1 hunks)
  • src/app/admin/login/page.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (5)
src/app/(with-header)/new/page.tsx (3)
src/app/(with-header)/(with-search-bar)/page.tsx (1)
  • metadata (28-54)
src/app/admin/login/page.tsx (1)
  • metadata (4-12)
src/app/layout.tsx (1)
  • metadata (13-17)
src/app/(with-header)/(with-search-bar)/page.tsx (3)
src/app/layout.tsx (1)
  • metadata (13-17)
src/app/(with-header)/new/page.tsx (1)
  • metadata (4-13)
src/app/admin/login/page.tsx (1)
  • metadata (4-12)
src/app/admin/login/page.tsx (3)
src/app/(with-header)/new/page.tsx (1)
  • metadata (4-13)
src/app/(with-header)/(with-search-bar)/page.tsx (1)
  • metadata (28-54)
src/app/layout.tsx (1)
  • metadata (13-17)
src/app/(with-header)/recipe/[id]/page.tsx (2)
src/app/(with-header)/edit/[id]/page.tsx (1)
  • generateMetadata (6-35)
src/types.ts (1)
  • RecipeData (1-7)
src/app/(with-header)/(with-search-bar)/search/page.tsx (2)
src/app/(with-header)/recipe/[id]/page.tsx (1)
  • generateMetadata (6-34)
src/app/(with-header)/edit/[id]/page.tsx (1)
  • generateMetadata (6-35)
🔇 Additional comments (6)
src/app/(with-header)/new/page.tsx (1)

4-13: SEO 메타데이터 추가가 잘 되었습니다.

레시피 작성 페이지에 적절한 메타데이터가 추가되었습니다. 특히 robots: "noindex, nofollow" 설정을 통해 검색 엔진에서 이 작성 페이지가 색인되지 않도록 한 점이 좋습니다. 콘텐츠 생성 페이지는 일반적으로 검색 결과에 나타날 필요가 없기 때문입니다.

src/app/layout.tsx (1)

15-16: 레이아웃 메타데이터 개선이 잘 되었습니다.

기본 "Generated by create next app" 설명을 의미 있는 한국어 설명으로 변경하고 robots: "index, follow" 지시문을 추가한 것은 SEO에 도움이 됩니다. 이를 통해 검색 엔진은 사이트를 색인화하고 링크를 따라갈 수 있습니다.

src/app/(with-header)/(with-search-bar)/page.tsx (1)

28-54: 상세한 메타데이터 구현이 잘 되었습니다.

메인 페이지에 상세한 메타데이터 구현이 인상적입니다. 제목, 설명, 키워드, Open Graph 속성, 그리고 정규 URL(canonical URL)까지 SEO에 필요한 모든 요소가 포함되어 있습니다. 특히 다음 사항이 훌륭합니다:

  1. 한국어 로케일(locale: "ko_KR") 지정
  2. 다양한 키워드 포함
  3. 정규 URL 설정으로 중복 콘텐츠 문제 방지

이러한 구현은 검색 엔진 최적화와 소셜 미디어 공유에 큰 도움이 될 것입니다.

src/app/(with-header)/(with-search-bar)/search/page.tsx (1)

5-5: Metadata 타입 임포트 추가

SEO를 위한 메타데이터 기능을 구현하기 위해 필요한 Metadata 타입을 적절하게 추가했습니다.

src/app/(with-header)/edit/[id]/page.tsx (1)

4-5: Metadata 타입 임포트 추가

메타데이터 기능 구현을 위한 Metadata 타입을 적절하게 임포트했습니다.

src/app/(with-header)/recipe/[id]/page.tsx (1)

3-3: Metadata 타입 임포트 추가

SEO 메타데이터 구현을 위한 필수 타입을 올바르게 임포트했습니다.

@Stilllee Stilllee deleted the feature/seo branch April 4, 2025 14:54
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