Use Cases

Sanity CMS: Claude Code 활용 가이드

sanity cms: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.

Sanity CMS개발をClaude Code로 효율화하기

Sanityは실시간コラボレーションと커스터마이징性の高いスタジオが特徴のヘッドレスCMSです。GROQという独自쿼리言語と、Reactベースの관리画面を自由に커스터마이징できる点が魅力です。Claude Code를 활용하면 Sanityの스키마설계やGROQ쿼리も효율적으로구축할 수 있습니다。

프로젝트のセットアップ

> Sanity프로젝트를 생성해줘。
> Next.js App Routerと연동する구성で。
npm create sanity@latest -- --project-id=xxxxx --dataset=production

# Next.jsプロジェクトにSanityクライアントを追加
npm install next-sanity @sanity/image-url

스키마定義

> ブ로그글と著者のSanity스키마を作って。
> リッチテキスト、이미지、参照フィールドを含めて。
// sanity/schemas/post.ts
import { defineType, defineField } from 'sanity';

export const postType = defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
      validation: (rule) => rule.required().max(100),
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: { source: 'title', maxLength: 96 },
      validation: (rule) => rule.required(),
    }),
    defineField({
      name: 'author',
      title: 'Author',
      type: 'reference',
      to: [{ type: 'author' }],
    }),
    defineField({
      name: 'mainImage',
      title: 'Main Image',
      type: 'image',
      options: { hotspot: true },
      fields: [
        defineField({
          name: 'alt',
          title: 'Alt Text',
          type: 'string',
        }),
      ],
    }),
    defineField({
      name: 'publishedAt',
      title: 'Published At',
      type: 'datetime',
    }),
    defineField({
      name: 'categories',
      title: 'Categories',
      type: 'array',
      of: [{ type: 'reference', to: [{ type: 'category' }] }],
    }),
    defineField({
      name: 'body',
      title: 'Body',
      type: 'blockContent',
    }),
  ],
  preview: {
    select: {
      title: 'title',
      author: 'author.name',
      media: 'mainImage',
    },
    prepare({ title, author, media }) {
      return { title, subtitle: author, media };
    },
  },
});

GROQ쿼리の설계

> ブ로그글목록と상세페이지用のGROQ쿼리を書いて。
> 著者情報と카테고리も전개して취득して。
// src/lib/sanity/queries.ts
import { groq } from 'next-sanity';

// 글목록
export const postsQuery = groq`
  *[_type == "post" && defined(slug.current)] | order(publishedAt desc) {
    _id,
    title,
    "slug": slug.current,
    publishedAt,
    excerpt,
    mainImage {
      asset-> {
        _id,
        url,
        metadata { dimensions, lqip }
      },
      alt
    },
    author-> {
      name,
      "slug": slug.current,
      image { asset-> { url } }
    },
    categories[]-> {
      title,
      "slug": slug.current
    }
  }[0...$limit]
`;

// 個別글
export const postBySlugQuery = groq`
  *[_type == "post" && slug.current == $slug][0] {
    _id,
    title,
    "slug": slug.current,
    publishedAt,
    body[] {
      ...,
      _type == "image" => {
        ...,
        asset-> { url, metadata { dimensions } }
      }
    },
    mainImage {
      asset-> { url, metadata { dimensions, lqip } },
      alt
    },
    author-> {
      name,
      bio,
      image { asset-> { url } }
    },
    categories[]-> {
      title,
      "slug": slug.current
    },
    "relatedPosts": *[
      _type == "post" &&
      slug.current != $slug &&
      count(categories[@._ref in ^.^.categories[]._ref]) > 0
    ] | order(publishedAt desc) [0...3] {
      title,
      "slug": slug.current,
      publishedAt,
      mainImage { asset-> { url } }
    }
  }
`;

Next.jsでの데이터취득

// src/lib/sanity/client.ts
import { createClient } from 'next-sanity';

export const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
  apiVersion: '2024-01-01',
  useCdn: process.env.NODE_ENV === 'production',
});

// app/blog/page.tsx
import { client } from '@/lib/sanity/client';
import { postsQuery } from '@/lib/sanity/queries';

export default async function BlogPage() {
  const posts = await client.fetch(postsQuery, { limit: 20 });

  return (
    <div className="max-w-4xl mx-auto p-6">
      <h1 className="text-3xl font-bold mb-8">ブログ</h1>
      {posts.map((post: any) => (
        <article key={post._id} className="mb-8 border-b pb-6">
          <h2 className="text-xl font-bold">{post.title}</h2>
          <p className="text-gray-500 text-sm">{post.author?.name}</p>
        </article>
      ))}
    </div>
  );
}

정리

SanityのGROQ쿼리と커스터마이징可能なスタジオは、柔軟な콘텐츠관리を実現します。Claude Codeを활용すれば、스키마설계やGROQの記述も효율적으로進められます。ブ로그CMS구축가이드Next.js풀스택개발도 참고하세요.

Sanity의 상세 정보는Sanity공식 문서를 참고하세요.

#Claude Code #Sanity #CMS #ヘッドレスCMS #GROQ