Strapi CMS 1차 개선#445
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughStrapi 관련 환경 변수 추가, Next.js 이미지 원격 패턴 및 CSP img-src 확장, Strapi 데이터 조회 정렬/카테고리 정렬 로직 추가, 인사이트 페이지에서 서버측 카테고리 필터링을 클라이언트측 필터링으로 전환하고 최근 표시 및 설명 콜아웃을 추가했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as 브라우저 (Client)
participant Server as Next.js Server
participant Strapi as Strapi API
Client->>Server: /insights 페이지 요청 (possible ?category=slug)
Server->>Strapi: fetchCategories()
Strapi-->>Server: 카테고리 목록 응답
Server->>Strapi: fetchArticles(sort=publishedAt:desc)
Strapi-->>Server: 전체 게시글 응답 (모든 카테고리)
Server-->>Client: 렌더링된 페이지 + allArticles, categories (서버측 렌더링)
Client->>Client: 쿼리 파람에 따라 클라이언트측으로 articles 필터링
Client->>Client: recent(3일) 검사로 마커 추가 및 카테고리 설명 표시
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20분 시
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/app/(service)/insights/page.tsx (1)
77-86:⚠️ Potential issue | 🟡 Minor코딩 가이드라인 위반: 템플릿 리터럴 대신
cn()사용 필요"전체" 탭의 className에서 템플릿 리터럴을 사용하고 있습니다. 코딩 가이드라인에 따르면 className 조합에는 항상
cn()유틸리티를 사용해야 합니다. 아래 카테고리 탭(lines 91-96)에서는 올바르게cn()을 사용하고 있으므로 일관성을 유지해 주세요.🔧 제안된 수정
<Link href="/insights" - className={`shrink-0 whitespace-nowrap px-300 pb-200 transition-colors ${ - !selectedCategorySlug - ? 'font-designer-18b border-b-2 border-text-strong text-text-strong' - : 'font-designer-18r text-text-subtle hover:text-text-strong' - }`} + className={cn( + 'shrink-0 whitespace-nowrap px-300 pb-200 transition-colors', + !selectedCategorySlug + ? 'font-designer-18b border-b-2 border-text-strong text-text-strong' + : 'font-designer-18r text-text-subtle hover:text-text-strong', + )} >As per coding guidelines: "Always use
cn()utility for className composition. Never use template literal className strings."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(service)/insights/page.tsx around lines 77 - 86, Replace the template-literal className on the "전체" Link with the same cn() utility used by the other category tabs: update the Link component that references selectedCategorySlug to call cn() and pass the static classes plus conditional classes (the active vs inactive class strings currently inside the template literal) as arguments so the logic mirrors the category tab implementation; ensure you import/retain the cn utility and keep the conditional check on selectedCategorySlug unchanged.src/api/strapi/api/fetch-articles.ts (1)
66-75:⚠️ Potential issue | 🔴 Critical
fetchArticles()호출에서 불필요한 인자 전달 - 호환성 오류
fetchArticles()함수 시그니처가 변경되어 매개변수를 더 이상 받지 않습니다. 그러나src/app/(service)/insights/weekly/page.tsx라인 50에서 여전히fetchArticles(selectedCategorySlug)로 인자를 전달하고 있습니다.src/app/(service)/insights/page.tsx라인 48-56에서처럼 필터링 로직을 클라이언트 측으로 이동하도록 업데이트하거나, 인자 없이fetchArticles()만 호출하도록 수정해야 합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/strapi/api/fetch-articles.ts` around lines 66 - 75, fetchArticles() no longer accepts arguments but is still being called with selectedCategorySlug in the weekly insights page; remove the argument and either call fetchArticles() directly or move the category filtering to the client like the other insights page does. Update the caller (the weekly page component where fetchArticles(selectedCategorySlug) is used) to call fetchArticles() with no params, then apply the selectedCategorySlug filter to the returned array (or replicate the client-side filtering approach used in the main insights page) so the call matches the fetchArticles() signature.
🧹 Nitpick comments (4)
.env.example (1)
4-5: 환경 변수 정렬 순서 및 파일 끝 빈 줄 누락정적 분석 도구에서 두 가지 경고가 발생했습니다:
NEXT_PUBLIC_STRAPI_URL이 알파벳 순서상NEXT_PUBLIC_TOSS_CLIENT_KEY앞에 와야 합니다.- 파일 끝에 빈 줄이 없습니다.
🔧 제안된 수정
NEXT_PUBLIC_API_BASE_URL= NEXT_PUBLIC_KAKAO_CLIENT_ID= NEXT_PUBLIC_GOOGLE_CLIENT_ID= -NEXT_PUBLIC_TOSS_CLIENT_KEY= NEXT_PUBLIC_STRAPI_URL= +NEXT_PUBLIC_TOSS_CLIENT_KEY= +🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.env.example around lines 4 - 5, Reorder the environment variables so NEXT_PUBLIC_STRAPI_URL appears before NEXT_PUBLIC_TOSS_CLIENT_KEY and add a trailing newline at the end of the .env.example file; specifically swap the two lines containing NEXT_PUBLIC_STRAPI_URL and NEXT_PUBLIC_TOSS_CLIENT_KEY to follow alphabetical order and ensure the file ends with a blank line.src/app/(service)/insights/page.tsx (3)
108-120: IIFE 패턴을 더 간결하게 리팩토링 고려현재 IIFE(즉시 실행 함수 표현식) 패턴을 사용하고 있습니다. 기능상 문제는 없지만, 변수 추출 방식으로 더 읽기 쉽게 작성할 수 있습니다.
♻️ 제안된 리팩토링
컴포넌트 상단(예: line 64 이후)에 변수를 추출하고 JSX에서 직접 사용:
const categoryDescription = selectedCategorySlug ? categories.find((c) => c.slug === selectedCategorySlug)?.description : '🧑🍳 카테고리별로 특화된 인사이트들이 준비되어 있어요.';JSX에서:
{/* 카테고리 description 콜아웃 */} {categoryDescription && ( <div className="flex items-start gap-300 rounded-r-150 border-l-2 border-pink-500 bg-background-accent-pink-subtle px-400 py-300"> <p className="font-designer-18r text-text-subtle">{categoryDescription}</p> </div> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(service)/insights/page.tsx around lines 108 - 120, Extract the IIFE logic into a top-level variable (e.g., create const categoryDescription) computed from selectedCategorySlug and categories (use categories.find(c => c.slug === selectedCategorySlug)?.description with the fallback string), then replace the IIFE in the JSX with a simple conditional render that uses categoryDescription && (...) to render the same div/p elements; update references to selectedCategorySlug and categories accordingly so the display logic lives outside the JSX.
67-67: 코딩 가이드라인 위반: Tailwind 임의 값 사용
max-w-[1280px]는 임의 값(arbitrary value)을 사용하고 있습니다. 코딩 가이드라인에서는 프로젝트 커스텀 디자인 토큰만 사용하도록 권장합니다. 프로젝트 학습 내용에 따르면w-7xl이 80rem(1280px)으로 유효하므로,max-w-7xl을 사용할 수 있는지 확인해 주세요.♻️ 제안된 수정
- <div className="mx-auto w-full max-w-[1280px] px-200 py-400 sm:px-300 sm:py-500 xl:px-400 xl:py-600"> + <div className="mx-auto w-full max-w-7xl px-200 py-400 sm:px-300 sm:py-500 xl:px-400 xl:py-600">Based on learnings: "treat 'w-7xl' as a valid Tailwind CSS v4 width utility (from the container scale) equivalent to 80rem (1280px)."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(service)/insights/page.tsx at line 67, Replace the arbitrary Tailwind value max-w-[1280px] with the project token max-w-7xl in the className on the div (the container div in insights page.tsx) so it uses the approved design token; update the class string to use max-w-7xl, verify tailwind config supports the 7xl size, and ensure the surrounding responsive padding classes (px-200, py-400, etc.) remain unchanged and visual layout is validated after the change.
151-151: 코딩 가이드라인 위반: 이미지 크기에 임의 값 사용
h-[80px],w-[80px],h-[120px],w-[120px]는 임의 값을 사용하고 있습니다. 가능하다면 프로젝트의 spacing/sizing 토큰을 사용하거나, 해당 크기에 대한 커스텀 토큰 정의를 고려해 주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/`(service)/insights/page.tsx at line 151, The div using className "rounded-100 relative h-[80px] w-[80px] flex-shrink-0 overflow-hidden sm:h-[120px] sm:w-[120px]" uses arbitrary pixel sizes; replace those arbitrary utilities with your project's spacing/sizing tokens (or add custom tokens in tailwind config) and update the className on that div accordingly (e.g., use existing height/width tokens like h-<token> w-<token> and sm:h-<token> sm:w-<token> or create and use new tokens in theme.extend.height/width if no suitable tokens exist).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@next.config.ts`:
- Around line 119-123: The CSP img-src directive in your config is missing the
production domain blog.zeroone.it.kr while remotePatterns already includes it;
update the CSP configuration (the img-src entry in next.config.ts) to include
both 'test-blog.zeroone.it.kr' and 'blog.zeroone.it.kr' so direct image loads
aren’t blocked (ensure the same host appears in the CSP img-src string where CSP
is defined and keep remotePatterns unchanged).
In `@src/api/strapi/api/fetch-articles.ts`:
- Around line 83-91: Add a blank line before the final return to satisfy
ESLint's "padding-line-between-statements" rule: after computing sorted (the
constant defined via const sorted = [...res.data].sort(...)) and before the
return { ...res, data: sorted }; insert a single empty line; no other logic
changes needed—leave CATEGORY_SLUG_ORDER and sorting logic intact.
---
Outside diff comments:
In `@src/api/strapi/api/fetch-articles.ts`:
- Around line 66-75: fetchArticles() no longer accepts arguments but is still
being called with selectedCategorySlug in the weekly insights page; remove the
argument and either call fetchArticles() directly or move the category filtering
to the client like the other insights page does. Update the caller (the weekly
page component where fetchArticles(selectedCategorySlug) is used) to call
fetchArticles() with no params, then apply the selectedCategorySlug filter to
the returned array (or replicate the client-side filtering approach used in the
main insights page) so the call matches the fetchArticles() signature.
In `@src/app/`(service)/insights/page.tsx:
- Around line 77-86: Replace the template-literal className on the "전체" Link
with the same cn() utility used by the other category tabs: update the Link
component that references selectedCategorySlug to call cn() and pass the static
classes plus conditional classes (the active vs inactive class strings currently
inside the template literal) as arguments so the logic mirrors the category tab
implementation; ensure you import/retain the cn utility and keep the conditional
check on selectedCategorySlug unchanged.
---
Nitpick comments:
In @.env.example:
- Around line 4-5: Reorder the environment variables so NEXT_PUBLIC_STRAPI_URL
appears before NEXT_PUBLIC_TOSS_CLIENT_KEY and add a trailing newline at the end
of the .env.example file; specifically swap the two lines containing
NEXT_PUBLIC_STRAPI_URL and NEXT_PUBLIC_TOSS_CLIENT_KEY to follow alphabetical
order and ensure the file ends with a blank line.
In `@src/app/`(service)/insights/page.tsx:
- Around line 108-120: Extract the IIFE logic into a top-level variable (e.g.,
create const categoryDescription) computed from selectedCategorySlug and
categories (use categories.find(c => c.slug ===
selectedCategorySlug)?.description with the fallback string), then replace the
IIFE in the JSX with a simple conditional render that uses categoryDescription
&& (...) to render the same div/p elements; update references to
selectedCategorySlug and categories accordingly so the display logic lives
outside the JSX.
- Line 67: Replace the arbitrary Tailwind value max-w-[1280px] with the project
token max-w-7xl in the className on the div (the container div in insights
page.tsx) so it uses the approved design token; update the class string to use
max-w-7xl, verify tailwind config supports the 7xl size, and ensure the
surrounding responsive padding classes (px-200, py-400, etc.) remain unchanged
and visual layout is validated after the change.
- Line 151: The div using className "rounded-100 relative h-[80px] w-[80px]
flex-shrink-0 overflow-hidden sm:h-[120px] sm:w-[120px]" uses arbitrary pixel
sizes; replace those arbitrary utilities with your project's spacing/sizing
tokens (or add custom tokens in tailwind config) and update the className on
that div accordingly (e.g., use existing height/width tokens like h-<token>
w-<token> and sm:h-<token> sm:w-<token> or create and use new tokens in
theme.extend.height/width if no suitable tokens exist).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8f6d7aff-94bd-4570-86cb-d662e945b533
📒 Files selected for processing (4)
.env.examplenext.config.tssrc/api/strapi/api/fetch-articles.tssrc/app/(service)/insights/page.tsx
🌱 연관된 이슈
없음
☘️ 작업 내용
카테고리 중 인사이트 랩을 1번째로 바꿨습니다
제로원 운영서버 인사이트에서 이미지 엑박 떠서 nextconfig 파일에 Strapi 운영서버 주소가 누락되어 있어서 추가했습니다
그밖에 목록에 카테고리 설명을 띄우고 폰트 사이즈 ⬆️ 등의 스타일링을 추가했습니다
🍀 참고사항
현재 테스트서버 인사이트는 이미지가 잘 뜨고 운영서버까지 머지한 후에 엑박 없어지는지 검증 가능합니다
스크린샷 (선택)
Summary by CodeRabbit
New Features
Chores
Style