Contentful, Next.js 및 Zod를 사용한 서식 있는 텍스트 및 이미지

이전 기사에서는 기존 Contentful 모델에 대해 코드베이스에서 모델을 생성하여 완전히 형식이 안전한 방식으로 모델을 가져오고 상호 작용할 수 있는 방법을 보여주었습니다. 또한 이미지와 서식 있는 텍스트로 작업하는 방법과 이전 자습서의 컨텍스트 개체가 수행할 작업에 대해서도 암시했습니다.

더 읽어보기



이전 기사에서는 Contentful 모델 작업에 유용한 추상화를 제공하는 createContentfulModel 함수를 만드는 방법을 살펴보았습니다.

이 문서에서는 이미지를 최적화된 차세대 형식 등으로 자동으로 가져올 수 있는 contentfulImage 함수를 만드는 방법을 살펴보겠습니다.

콘텐츠 이미지 및 서식 있는 텍스트에 대한 스키마 설정



콘텐츠 이미지 필드는 일반 콘텐츠 항목입니다. 이전 기사에서 생성한 contentfulEntrySchema를 사용하여 이미지 필드 및 이미지 항목 자체에 대한 스키마를 생성합니다.

import { z } from "zod";
import { contentfulEntrySchema } from "./contentfulEntrySchema";

export const contentfulImageFieldsSchema = z.object({
  title: z.string(),
  description: z.string(),
  file: z.object({
    url: z.string(),
    details: z.object({
      size: z.number().positive().int(),
      image: z.object({
        width: z.number().positive().int(),
        height: z.number().positive().int(),
      }),
    }),
    fileName: z.string(),
    contentType: z.string(),
  }),
});

export const contentfulImageField = () =>
  contentfulEntrySchema.extend({
    fields: contentfulImageFieldsSchema,
  });


또한 서식 있는 텍스트 필드에 대한 유형을 설정할 것입니다. 지금은 바로 가기를 사용하고 Zod 변환과 함께 typecast를 사용하고 Contentful 리치 텍스트의 모양이 매우 복잡하기 때문에 실제 데이터 유효성 검사를 수행하지 않습니다.

import { z } from "zod";
import { RichTextContent } from "contentful";

export const contentfulRichTextField = () =>
  z.any().transform((x) => x as RichTextContent);


컨텍스트 개체를 사용하여 모든 사용자 지정 Contentful 필드 제공



이제 우리가 컨텍스트 객체로 무엇을 하려고 했는지 밝힐 때입니다. (참고: 컨텍스트 개체는 사용자 지정 필드를 제공하는 것보다 훨씬 더 많은 작업을 수행하도록 확장할 수 있지만 이것부터 시작하겠습니다).

컨텍스트 개체에는 contentfulFields 속성이 포함되며 이 속성에는 우리가 정의한 두 스키마가 모두 포함됩니다. 컨텍스트 유형은 다음과 같이 업데이트됩니다.

export type CreateContentfulModelContext = {
  contentfulFields: {
    richText: typeof contentfulRichTextField;
    image: typeof contentfulImageField;
  };
};


이제 createContentfulModel에서 컨텍스트를 만들고 fieldsSchemaCreator 함수에 제공해야 합니다.

// ... more imports
import { contentfulImageField } from "./contentful-image-field";
import { contentfulRichTextField } from "./contentful-rich-text-field";

// ... types

export function createContentfulModel<TDataIn extends {}, TDataOut>(
    contentType: string,
    fieldsSchemaCreator: FieldsSchemaCreator<TDataIn, TDataOut>
) {

    // Set up context
    const context: CreateContentfulModelContext = {
    contentfulFields: {
      richText: contentfulRichTextField,
      image: contentfulImageField,
    },
  };

    // Provide context to fields schema creator
    const fieldsSchema = fieldsSchemaCreator(context);

    // ... Rest of the function
}


이제 모든 필드 스키마 작성자 함수는 새로 생성된 필드 유형에 액세스할 수 있습니다. 다음으로 어떻게 사용할 수 있는지 봅시다.

이미지 및 서식 있는 텍스트 필드 유형 사용



컨텍스트 개체의 새 필드를 사용하여 이미지와 서식 있는 텍스트를 포함하도록 예제 모델을 업데이트해 보겠습니다.

import { z } from "zod";
import { createContentfulModel } from "./create-contentful-model";

export const exampleModel = createContentfulModel("example", (ctx) => z.object({
    title: z.string(),
    description: z.string().optional(),
    rating: z.number().int().positive(),
    body: ctx.contentfulFields.richText(),
    image: ctx.contentfulFields.image(),
}));


거기. 그게 전부입니다.

풍부한 텍스트 및 이미지 사용



먼저 RichTextContent를 소품으로 사용하는 새로운 서식 있는 텍스트 구성 요소를 만들어 보겠습니다. 이를 위해 다음과 함께 설치할 수 있는 @contentful/rich-text-react-renderer를 사용할 것입니다.

npm i @contentful/rich-text-react-renderer


이 구성 요소는 간단하고 아래에 나와 있으며 단순히 documentToReactComponents 에 래핑된 <article> 메서드를 사용합니다. 그러나 이제 모든 서식 있는 텍스트를 사용자 지정하는 작업을 한 곳에서 수행할 수 있습니다.

import { documentToReactComponents } from "@contentful/rich-text-react-renderer";
import { RichTextContent } from "contentful"

export interface RichTextProps {
    content?: RichTextContent;
}

export function RichText(props: RichTextProps) {
    return <article>
        {documentToReactComponents(props.content as any)}
    </article>
}


이미지 자체에 이미지에 대한 src로 직접 사용할 수 있는 파일의 URL이 포함되어 있으므로 이미지 소비가 간단합니다. 마찬가지로 alt 에 대한 제목이 포함되어 있습니다.

간단한 React 애플리케이션을 업데이트하여 이미지와 서식 있는 텍스트 콘텐츠를 모두 렌더링해 보겠습니다.

<ul>
        {
            examples.map(example => (
                <li key={example.sys.id}>
                    <img
                        src={example.fields.image.fields.file.url}
                        alt={example.fields.image.fields.title}
                    />
                    <p>{example.fields.title}</p>
                    <p>{example.fields.description}</p>
                    <p>{example.fields.rating} / 5</p>
                    <RichText content={example.fields.body} />
                </li>
            ))
        }
    </ul>


. 예를 들어 문서에 설명된 방법 또는 패키지를 사용하여 src={entry.fields.image.fields.file.url}를 개선된 src={contentfulImage(entry.fields.image, { format: "webp", quality: 60 })}로 교체하거나 다음을 사용하여 contentful-image를 직접 설치합니다.

npm i contentful-image


그게 다야.



시간을 내어 이 기사를 읽어주셔서 감사합니다. 도움이 되셨기를 바랍니다.

좋은 웹페이지 즐겨찾기