Skip to content

Strapi CMS 1차 개선#445

Merged
dongjooyun merged 3 commits into
developfrom
strapi
Mar 24, 2026
Merged

Strapi CMS 1차 개선#445
dongjooyun merged 3 commits into
developfrom
strapi

Conversation

@dongjooyun

@dongjooyun dongjooyun commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

🌱 연관된 이슈

없음

☘️ 작업 내용

카테고리 중 인사이트 랩을 1번째로 바꿨습니다
제로원 운영서버 인사이트에서 이미지 엑박 떠서 nextconfig 파일에 Strapi 운영서버 주소가 누락되어 있어서 추가했습니다
그밖에 목록에 카테고리 설명을 띄우고 폰트 사이즈 ⬆️ 등의 스타일링을 추가했습니다

🍀 참고사항

현재 테스트서버 인사이트는 이미지가 잘 뜨고 운영서버까지 머지한 후에 엑박 없어지는지 검증 가능합니다

스크린샷 (선택)

Summary by CodeRabbit

  • New Features

    • 아티클이 발행일 기준 내림차순으로 항상 표시되도록 변경
    • 최근 3일 이내 발행된 아티클에 시각적 표시 추가
    • 카테고리 선택 시 해당 카테고리 설명을 목록 상단에 표시
  • Chores

    • 환경 변수 샘플에 NEXT_PUBLIC_STRAPI_URL 항목 추가
    • 이미지 로드 허용 호스트에 새 도메인 추가
  • Style

    • 편집기 포맷터 설정 변경(타입스크립트용)

@vercel

vercel Bot commented Mar 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
study-platform-client-dev Error Error Mar 24, 2026 8:56pm

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c98bf6d-9f33-4746-b190-1ad282769a3f

📥 Commits

Reviewing files that changed from the base of the PR and between 1bdbe3f and 5df8439.

📒 Files selected for processing (4)
  • .vscode/settings.json
  • next.config.ts
  • src/api/strapi/api/fetch-articles.ts
  • src/app/(service)/insights/page.tsx
✅ Files skipped from review due to trivial changes (1)
  • .vscode/settings.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/(service)/insights/page.tsx

📝 Walkthrough

Walkthrough

Strapi 관련 환경 변수 추가, Next.js 이미지 원격 패턴 및 CSP img-src 확장, Strapi 데이터 조회 정렬/카테고리 정렬 로직 추가, 인사이트 페이지에서 서버측 카테고리 필터링을 클라이언트측 필터링으로 전환하고 최근 표시 및 설명 콜아웃을 추가했습니다.

Changes

Cohort / File(s) Summary
환경 설정
\.env\.example
NEXT_PUBLIC_STRAPI_URL 환경 변수 추가 및 파일 끝줄 개행 추가.
Next.js 설정
next.config.ts
CSP img-srchttps://blog.zeroone.it.kr 허용 추가; images.remotePatternshttps://blog.zeroone.it.kr/uploads/** 원격 패턴 추가(기존 테스트 CMS 패턴 유지/조정).
Strapi API 통합
src/api/strapi/api/fetch-articles.ts
fetchArticlessort=publishedAt:desc 적용(카테고리 필터 유지 가능); fetchCategories 결과를 비동기(await) 처리해 CATEGORY_SLUG_ORDER 기준으로 정렬하여 응답의 data를 재할당.
Insights 페이지 변경
src/app/(service)/insights/page.tsx
서버에서 카테고리별로 제한하던 로직을 모든 글을 서버로 가져온 뒤 클라이언트에서 필터링하도록 변경; Banner 제거 후 cn 유틸로 클래스 조합; 최근(3일) 게시물 마커 및 선택된 카테고리 설명 콜아웃 추가; 탭 레이아웃/타이포그래피 조정.
편집기 설정
.vscode/settings.json
TypeScript의 editor.defaultFormatterbiomejs.biome에서 esbenp.prettier-vscode로 변경.

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일) 검사로 마커 추가 및 카테고리 설명 표시
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20분

🐰 새 URL 넣고 깡충깡충,
카테고리 순서도 정리했지롱,
서버에선 전부 끌어오고 나는 골라보며,
최근은 분홍 점으로 반짝,
이미지도 멀리서 편히 불러오네 🌸

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 주요 변경사항과 충분히 관련이 있습니다. 'Strapi CMS 1차 개선'은 PR의 핵심 목표인 Strapi CMS 운영 서버 통합, 카테고리 순서 정렬, 이미지 문제 해결, UI 개선 등을 포괄적으로 나타냅니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch strapi

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: 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: 환경 변수 정렬 순서 및 파일 끝 빈 줄 누락

정적 분석 도구에서 두 가지 경고가 발생했습니다:

  1. NEXT_PUBLIC_STRAPI_URL이 알파벳 순서상 NEXT_PUBLIC_TOSS_CLIENT_KEY 앞에 와야 합니다.
  2. 파일 끝에 빈 줄이 없습니다.
🔧 제안된 수정
 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

📥 Commits

Reviewing files that changed from the base of the PR and between b83424d and 1bdbe3f.

📒 Files selected for processing (4)
  • .env.example
  • next.config.ts
  • src/api/strapi/api/fetch-articles.ts
  • src/app/(service)/insights/page.tsx

Comment thread next.config.ts
Comment thread src/api/strapi/api/fetch-articles.ts
@dongjooyun dongjooyun merged commit fc46d4b into develop Mar 24, 2026
8 of 9 checks passed
@dongjooyun dongjooyun deleted the strapi branch March 24, 2026 18:29
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