Skip to content

SEO 관련 기능 개선 및 레시피 단일 조회 테스트 추가#26

Merged
Stilllee merged 6 commits intodevelopfrom
refactor/seo
Apr 4, 2025
Merged

SEO 관련 기능 개선 및 레시피 단일 조회 테스트 추가#26
Stilllee merged 6 commits intodevelopfrom
refactor/seo

Conversation

@Stilllee
Copy link
Owner

@Stilllee Stilllee commented Apr 4, 2025

변경 사항

메타데이터 개선

  • 관리자 로그인 페이지에 robots 메타태그 추가
  • 검색 쿼리가 없을 때의 메타데이터 설정

코드 구조 개선

  • 단일 레시피 조회 로직 분리
  • NotFound 페이지에서 리다이렉트 버튼을 컴포넌트화하여 서버 컴포넌트로 유지
  • 불필요한 세미콜론 제거

테스트 및 에러 처리:

  • 레시피 단일 조회 기능에 대한 테스트 추가
  • 에러 메시지 및 에러 컴포넌트 수정으로 UI 개선

관련 이슈

Summary by CodeRabbit

  • 신규 기능
    • 검색 페이지가 검색어가 없을 경우 전체 레시피 정보를 기본으로 표시합니다.
    • 관리자 로그인 페이지에 검색 엔진 노출을 제한하는 메타 태그가 추가되었습니다.
    • 오류 및 없는 페이지에서 "홈으로 돌아가기" 버튼을 통한 내비게이션이 개선되었습니다.
  • 버그 수정/스타일 개선
    • 레시피 입력 폼의 불필요한 문법 수정으로 렌더링 안정성이 향상되었습니다.
  • 테스트
    • 내비게이션 버튼 및 레시피 데이터 로드 기능에 대한 테스트가 추가되었습니다.

@Stilllee Stilllee self-assigned this Apr 4, 2025
@coderabbitai
Copy link

coderabbitai bot commented Apr 4, 2025

Walkthrough

이번 PR에서는 여러 페이지의 메타데이터 생성 및 API 호출 로직이 개선되었습니다. 검색 페이지는 검색 쿼리가 없을 경우 기본 메타데이터를 반환하도록 변경되었고, 편집 및 레시피 페이지에서는 직접 API 호출 대신 getRecipe 유틸리티 함수를 사용하여 데이터 처리를 중앙집중화했습니다. 또한 JSX 문법 수정, 관리 페이지의 메타데이터에 로봇 지시문 추가, 에러 메시지 조건부 렌더링 개선과 함께 홈 버튼 컴포넌트와 해당 테스트 파일이 새로 도입되었습니다.

Changes

파일들 변경 요약
src/app/(with-header)/(with-search-bar)/search/page.tsx generateMetadata 함수에 검색 쿼리(q)가 없을 경우 기본 메타데이터 반환 조건 추가
src/app/(with-header)/edit/[id]/page.tsx
src/app/(with-header)/recipe/[id]/page.tsx
API 호출을 직접 수행하던 로직을 getRecipe 함수 호출로 대체하고, 관련 에러 핸들링 제거
src/app/(with-header)/new/page.tsx <RecipeForm />;에서 불필요한 세미콜론 제거하여 JSX 문법 수정
src/app/admin/login/page.tsx metadata 객체에 robots: "noindex, nofollow" 속성 추가
src/app/components/HomeButton.tsx
src/app/components/HomeButton.test.tsx
새 홈 버튼 컴포넌트 추가 및, 해당 컴포넌트의 렌더링과 내비게이션 기능을 검증하는 테스트 파일 추가
src/app/error.tsx 에러 메시지 표시 로직 수정: error.message가 존재하면 해당 메시지를, 그렇지 않으면 기본 텍스트 표시 및 불필요한 <br /> 제거
src/app/not-found.tsx 기존의 useRouter를 통한 내비게이션 대신 HomeButton 컴포넌트를 사용하여 홈으로 이동하도록 변경
src/util/getRecipe.ts
src/util/getRecipe.test.ts
API 호출 및 에러 핸들링 로직을 캡슐화한 getRecipe 함수와 이에 대한 테스트 추가

Sequence Diagram(s)

sequenceDiagram
    participant UI as 검색 페이지
    participant GM as generateMetadata
    UI->>GM: generateMetadata({ q }) 호출
    alt q가 falsy인 경우
        GM-->>UI: 기본 메타데이터 (타이틀, 설명, opengraph 등) 반환
    else q가 존재하는 경우
        GM-->>UI: 검색 쿼리에 따른 메타데이터 반환
    end
Loading
sequenceDiagram
    participant UI as 편집/레시피 페이지
    participant GR as getRecipe
    participant API as API 서버
    UI->>GR: getRecipe(id) 호출
    GR->>API: API 호출 (force-cache)
    alt 응답이 404인 경우
        API-->>GR: 404 응답
        GR->>UI: notFound 호출 또는 적절한 처리 수행
    else 에러 응답인 경우 (예: 500)
        API-->>GR: 에러 응답
        GR->>UI: 에러 발생 ("레시피 정보를 가져올 수 없습니다") 및 콘솔 로그 출력
    else 정상 응답인 경우
        API-->>GR: JSON 형식의 레시피 데이터 전송
        GR-->>UI: 레시피 데이터 반환
    end
Loading
sequenceDiagram
    participant User as 사용자
    participant HB as HomeButton 컴포넌트
    participant Router as Next.js 라우터
    User->>HB: 버튼 클릭
    HB->>Router: router.replace("/") 호출
    Router-->>User: 홈 페이지로 이동
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 d97e3fb 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 (3)
src/util/getRecipe.ts (1)

1-18: 잘 구현된 중앙화된 데이터 가져오기 함수입니다.

레시피 데이터를 가져오는 로직을 중앙화하여 재사용성과 일관성을 높인 좋은 접근법입니다. 에러 처리도 적절히 구현되어 있습니다.

다만, 현재 { cache: "force-cache" }를 고정적으로 사용하고 있는데, 이 방식은 빌드 시점에 데이터를 캐싱하고 재검증하지 않습니다. 레시피 데이터가 자주 변경된다면 사용자에게 오래된 데이터가 표시될 수 있습니다.

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

   // 나머지 코드는 동일

이렇게 수정하면 필요에 따라 다른 캐싱 전략을 선택할 수 있습니다. 예를 들어 관리자 페이지에서는 "no-store"를 사용하여 항상 최신 데이터를 가져올 수 있습니다.

src/util/getRecipe.test.ts (2)

19-41: 성공 케이스 테스트가 잘 구현되었습니다.

레시피 데이터를 성공적으로 가져오는 케이스에 대한 테스트가 잘 작성되었습니다. mock 데이터 설정, API 호출 검증, 반환값 검증이 모두 적절합니다.

데이터의 형태만 검증하는 것 외에도 데이터의 일관성도 검증하면 좋을 것 같습니다.

  expect(result).toEqual(mockRecipe);
+ // ID가 문자열로 전달되었지만 반환된 결과의 ID는 숫자인지 확인
+ expect(typeof result.id).toBe('number');

53-69: 에러 처리 테스트가 잘 구현되었습니다.

API가 실패 응답을 반환할 때 에러를 throw하고 콘솔에 에러 메시지를 기록하는지 적절히 검증하고 있습니다. 콘솔 스파이를 사용하여 로깅을 확인하고 테스트 후 복원하는 것도 좋은 방법입니다.

더 다양한 에러 상태 코드(예: 401, 403, 500)에 대한 테스트 케이스를 추가하는 것도 고려해볼 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5b4fc89 and 744ecf3.

📒 Files selected for processing (11)
  • src/app/(with-header)/(with-search-bar)/search/page.tsx (1 hunks)
  • src/app/(with-header)/edit/[id]/page.tsx (2 hunks)
  • src/app/(with-header)/new/page.tsx (1 hunks)
  • src/app/(with-header)/recipe/[id]/page.tsx (2 hunks)
  • src/app/admin/login/page.tsx (1 hunks)
  • src/app/components/HomeButton.test.tsx (1 hunks)
  • src/app/components/HomeButton.tsx (1 hunks)
  • src/app/error.tsx (1 hunks)
  • src/app/not-found.tsx (2 hunks)
  • src/util/getRecipe.test.ts (1 hunks)
  • src/util/getRecipe.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (5)
src/app/(with-header)/new/page.tsx (1)
src/app/components/RecipeForm.tsx (1)
  • RecipeForm (15-123)
src/app/not-found.tsx (1)
src/app/components/HomeButton.tsx (1)
  • HomeButton (5-15)
src/util/getRecipe.test.ts (1)
src/util/getRecipe.ts (1)
  • getRecipe (4-18)
src/app/components/HomeButton.test.tsx (1)
src/app/components/HomeButton.tsx (1)
  • HomeButton (5-15)
src/util/getRecipe.ts (1)
src/app/error.tsx (1)
  • Error (5-33)
🔇 Additional comments (18)
src/app/components/HomeButton.tsx (1)

1-15: 아주 깔끔하게 구현된 HomeButton 컴포넌트입니다.

사용자가 홈페이지로 돌아갈 수 있는 기능을 독립적인 컴포넌트로 분리하여 구현한 것이 좋습니다. "use client" 지시문을 사용하여 클라이언트 컴포넌트로 명확하게 표시했고, 라우팅 로직을 집중화함으로써 코드 재사용성과 유지보수성이 향상되었습니다.

router.replace("/")를 사용하여 현재 페이지를 홈 페이지로 대체하는 방식은 특히 404 페이지에서 브라우저 히스토리를 관리하기에 적합합니다.

src/app/components/HomeButton.test.tsx (1)

1-32: 테스트 케이스가 잘 구현되었습니다.

HomeButton 컴포넌트에 대한 테스트 커버리지가 적절합니다. 다음과 같은 좋은 테스트 관행이 적용되었습니다:

  1. useRouter 훅을 정확하게 모킹하여 테스트 환경에서 라우팅 기능을 제어
  2. getHomeButton 헬퍼 함수를 사용하여 코드 중복 방지
  3. 렌더링 테스트와 동작 테스트 두 가지 케이스를 모두 포함
  4. fireEvent를 사용하여 사용자 상호작용을 시뮬레이션하고 예상 동작 검증

모든 테스트가 명확한 목적을 가지고 있으며, 컴포넌트의 주요 기능을 완벽하게 검증합니다.

src/app/not-found.tsx (2)

1-1: 적절한 컴포넌트 임포트입니다.

HomeButton 컴포넌트를 올바르게 임포트하고 있습니다. 상대 경로를 사용하여 컴포넌트를 명확하게 참조하고 있습니다.


18-18: HomeButton 컴포넌트 통합이 잘 이루어졌습니다.

기존 버튼 구현을 재사용 가능한 HomeButton 컴포넌트로 대체한 것은 좋은 접근법입니다. 이 변경으로 다음과 같은 이점이 있습니다:

  1. 서버 컴포넌트에서 클라이언트 측 기능(useRouter)을 분리하여 코드 구조가 개선됨
  2. 코드 재사용성이 향상됨 - 다른 페이지에서도 동일한 홈 버튼을 쉽게 활용할 수 있음
  3. 각 컴포넌트의 책임이 명확해짐

이러한 리팩토링은 PR 목표에 부합하며 코드베이스의 유지보수성을 향상시킵니다.

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

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

JSX 반환문 내에서의 컴포넌트 뒤에 있던 불필요한 세미콜론을 올바르게 제거했습니다. 이는 코드 일관성과 가독성 향상에 도움이 됩니다.

src/app/admin/login/page.tsx (1)

12-12: 관리자 페이지에 robots 메타태그 추가

관리자 로그인 페이지에 "noindex, nofollow" robots 메타태그를 추가한 것은 매우 좋은 보안 관행입니다. 이는 검색 엔진이 관리자 페이지를 색인하지 않도록 하여 무단 접근 시도의 위험을 줄이는 데 도움이 됩니다. SEO 기능 개선 목표에 부합하는 적절한 변경사항입니다.

src/app/error.tsx (2)

18-20: 오류 메시지의 동적 처리 개선

오류 메시지를 정적 메시지에서 동적 메시지로 개선한 것은 좋은 변화입니다. 실제 error.message가 있는 경우 이를 표시하고, 없는 경우 기본 메시지를 폴백으로 사용하는 방식은 사용자에게 더 구체적인 오류 정보를 제공할 수 있어 문제 해결에 도움이 됩니다.


22-22: 안내 메시지 단순화

안내 메시지에서 불필요한 줄바꿈을 제거하고 텍스트를 단순화한 것은 UI의 일관성과 가독성을 향상시킵니다.

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

36-47: 검색 쿼리가 없는 경우의 메타데이터 처리

검색 쿼리가 없는 경우에 대한 메타데이터 처리를 추가한 것은 SEO 측면에서 매우 중요한 개선사항입니다. 이전에는 쿼리가 없는 경우 명시적인 메타데이터 처리가 없었으나, 이제 "전체 레시피"에 대한 적절한 제목과 설명을 제공함으로써 검색 엔진이 페이지 내용을 더 정확하게 이해할 수 있게 되었습니다. 이는 PR의 SEO 기능 개선 목표에 잘 부합합니다.

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

2-2: 유틸리티 함수 import 추가 적절함

레시피 데이터를 가져오는 중앙화된 유틸리티 함수를 사용하도록 적절히 import 되었습니다.


11-11: 데이터 가져오기 로직 개선

직접적인 fetch 호출 대신 중앙화된 getRecipe 함수를 사용함으로써 코드가 간결해지고 에러 처리가 일관되게 적용됩니다.


30-30: 데이터 가져오기 로직 개선

Page 컴포넌트에서도 getRecipe 함수를 사용하여 코드 중복을 제거하고 데이터 가져오기 로직을 단순화했습니다.

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

3-3: 유틸리티 함수 import 추가 적절함

레시피 데이터를 가져오는 중앙화된 유틸리티 함수를 사용하도록 적절히 import 되었습니다.


11-11: 데이터 가져오기 로직 개선

직접적인 fetch 호출 대신 중앙화된 getRecipe 함수를 사용함으로써 코드가 간결해지고 에러 처리가 일관되게 적용됩니다.


31-31: 데이터 가져오기 로직 개선

Page 컴포넌트에서도 getRecipe 함수를 사용하여 코드 중복을 제거하고 데이터 가져오기 로직을 단순화했습니다.

src/util/getRecipe.test.ts (3)

1-13: 테스트 설정이 잘 구성되어 있습니다.

전역 fetch API와 next/navigation의 notFound 함수를 올바르게 모킹했으며, 테스트 환경 변수도 적절히 설정되었습니다.


14-18: 테스트 설정이 적절합니다.

테스트 간 독립성을 보장하기 위해 beforeEach에서 모든 모킹을 초기화하는 좋은 접근 방식입니다.


43-51: 404 에러 처리 테스트가 잘 구현되었습니다.

API가 404 응답을 반환할 때 notFound 함수가 호출되는지 적절히 검증하고 있습니다.

@Stilllee Stilllee deleted the refactor/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