profound-logoProfound CMS
โŒ˜K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Hybrid

Collection of Pages with Components๊ตฌ์„ฑ ์š”์†Œ ์œ ํ˜•Setup server sent events (SSE) content refetch์–ด๋“œ๋ฏผ ํŒจ๋„ ํ”„๋ก์‹œ ์„ค์ •ํ…œํ”Œ๋ฆฟ ๋นŒ๋”์—์„œ ์Šคํฌ๋ฆฝํŒ…Project Scaffolding๋ฏธ๋””์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Headless

Quick startjson๊ณผ Claude ์ฝ”๋“œ์ปดํฌ๋„ŒํŠธ Zod ๊ฐ€์ ธ์˜ค๊ธฐ

REST API

REST API ๊ฐœ์š”get์›น์‚ฌ์ดํŠธ๋ฅผ CMS API์— ์—ฐ๊ฒฐํ•˜๊ธฐget๊ฒฝ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐget๋ผ์šฐํŠธ ๊ฐ€์ ธ์˜ค๊ธฐget๋ธ”๋ก ๊ฐ€์ ธ์˜ค๊ธฐgetCEL ์บ์‹œ๊ฐ€ ํฌํ•จ๋œ ๋ธ”๋ก ๊ฐ€์ ธ์˜ค๊ธฐget๋ธ”๋ก ์ƒ์„ฑ ๊ฐ€์ ธ์˜ค๊ธฐget์ปดํฌ๋„ŒํŠธ ๊ฐ€์ ธ์˜ค๊ธฐgetGET /components/{name}get๋ฐ์ดํ„ฐ์…‹ ์Šคํ‚ค๋งˆ ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐgetGET /content-changes (SSE)patchPATCH /dataset/{schema_name}post๊ฒŒ์‹œ๋ฌผ ๋ฒˆ์—ญpatch๋ฒˆ์—ญ ํŒจ์น˜get์‚ฌ์šฉ๋Ÿ‰ ๊ฐ€์ ธ์˜ค๊ธฐpostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

Quick start

์Šคํ‚ค๋งˆ์— ๊ด€ํ•œ ๊ฒŒ์‹œ๋ฌผ

ํƒ€์ž… ์•ˆ์ „ํ•œ Zod ์Šคํ‚ค๋งˆ ์ƒ์„ฑ

์ด ๊ธฐ๋Šฅ์€ ๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…์„ ํƒ€์ž… ์•ˆ์ „ํ•œ Zod ์Šคํ‚ค๋งˆ ํ˜•ํƒœ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ, ๋‹ค์Œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

  • TypeScript ์šฐ์„  ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ
  • ์ •์  ํƒ€์ž… ์ถ”๋ก 

์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ: https://zod.dev

์„ค์ •

Zod ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

  1. ํ•„์š”ํ•œ ์ข…์†์„ฑ์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค
  2. cms-renderer์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

apps/
  web/
    app/
      page.tsx
    scripts/
      generated-schema.ts   # ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ

์Šคํฌ๋ฆฝํŠธ: generated-schema.ts

import { fetchAllCustomSchemaFields, saveZodSchemaCode } from 'cms-renderer/lib/custom-schemas';
import { cmsConfig } from '../lib/cms-config';

async function main() {
  const { cmsUrl, websiteId, apiKey } = cmsConfig;

  if (!cmsUrl) {
    throw new Error(
      '[generate-schemas] NEXT_PUBLIC_CMS_API_URL์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋˜๋Š” .env ํŒŒ์ผ์—์„œ ์„ค์ •ํ•˜์„ธ์š”.'
    );
  }

  if (!websiteId) {
    throw new Error(
      '[generate-schemas] CMS_WEBSITE_ID๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋˜๋Š” .env ํŒŒ์ผ์—์„œ ์„ค์ •ํ•˜์„ธ์š”.'
    );
  }

  if (!apiKey) {
    throw new Error(
      '[generate-schemas] PROFOUND_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋˜๋Š” .env ํŒŒ์ผ์—์„œ ์„ค์ •ํ•˜์„ธ์š”.'
    );
  }

  const schemas = await fetchAllCustomSchemaFields({ cmsUrl, websiteId, apiKey });

  if (schemas.length === 0) {
    throw new Error(
      '[generate-schemas] API์—์„œ ๋ฐ˜ํ™˜๋œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. PROFOUND_API_KEY๊ฐ€ ์œ ํšจํ•˜๋ฉฐ ์˜ฌ๋ฐ”๋ฅธ ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.'
    );
  }

  console.log(
    `[generate-schemas] ${schemas.length}๊ฐœ์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค: ${schemas.map((s) => s.name).join(', ')}`
  );

  await saveZodSchemaCode(schemas, './generated/cms-schemas.ts');

  console.log('[generate-schemas] ์™„๋ฃŒ.');
}

main().catch((err) => {
  console.error('[generate-schemas] ์‹คํŒจ:', err);
  process.exit(1);
});

CMS ๊ตฌ์„ฑ ์˜ˆ์‹œ

export const cmsConfig = {
  cmsUrl: process.env.NEXT_PUBLIC_CMS_API_URL,
  apiKey: process.env.CMS_API_KEY,
  websiteId: '...',
};

package.json ๊ตฌ์„ฑ

์ฐธ๊ณ : tsconfig.json์ด ์—†๋‹ค๋ฉด --tsconfig ํ”Œ๋ž˜๊ทธ๋ฅผ ์ œ๊ฑฐํ•˜์„ธ์š”.

{
  "name": "web",
  "version": "0.1.0",
  "type": "module",
  "private": true,
  "scripts": {
    "generate-schemas": "tsx --tsconfig tsconfig.json scripts/generate-schemas.ts",
    "...": "..."
  },
  "dependencies": {
    "cms-renderer": "0.3.1",
    "zod": "^4.3.6",
    "...": "..."
  },
  "devDependencies": {
    "tsx": "^4.21.0",
    "object-hash": "^3.0.0",
    "...": "..."
  }
}

์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰

bun run generate-schemas

์˜ˆ์ œ ์ถœ๋ ฅ:

tsx --tsconfig tsconfig.json scripts/generate-schemas.ts
[generate-schemas] ๊ตฌ์„ฑ ์š”์†Œ 3๊ฐœ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค: post, categories, header
[generate-schemas] ์™„๋ฃŒ.

์—…๋ฐ์ดํŠธ๋œ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

apps/
  web/
    app/
      page.tsx
    scripts/
      generated-schema.ts
    generated/
      cms-schemas.ts   # ์ƒ์„ฑ๋œ Zod ์Šคํ‚ค๋งˆ

page.tsx์—์„œ์˜ ์‚ฌ์šฉ๋ฒ•

import type { PetFoodPost, SiteConfig } from '@/generated/cms-schemas';
import { petFoodPostSchema } from '@/generated/cms-schemas';

// ํƒ€์ž… ์•ˆ์ „ํ•œ ํŒŒ์‹ฑ์— ์‚ฌ์šฉ
petFoodPostSchema.parse(obj);

์ฐธ๊ณ  ์‚ฌํ•ญ

  • ์ƒ์„ฑ๋œ ํŒŒ์ผ์„ ํ™•์ธํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜์„ธ์š”
  • ๊ตฌ์„ฑ ์š”์†Œ ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์„ธ์š”:
bun run generate-schemas
  • ๊ฐœ๋ฐœ ๋˜๋Š” ๋นŒ๋“œ ์›Œํฌํ”Œ๋กœ์— ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
  • ๊ด€๋ฆฌ์ž ํŒจ๋„์—์„œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ๋’ค, ๋กœ์ปฌ์—์„œ ๋‹ค์‹œ ์ƒ์„ฑํ•˜์„ธ์š”
Continue Reading
Nextjson๊ณผ Claude ์ฝ”๋“œโ€บ