컨텐츠로 건너뛰기

Astro 콘텐츠 로더 API

Astro의 콘텐츠 로더 API를 사용하면 로컬 또는 원격의 모든 소스에서 데이터를 로드하고 콘텐츠 컬렉션을 관리하기 위해 Astro의 콘텐츠 레이어와 상호 작용할 수 있습니다.

Astro 로더를 사용하면 페이지와 컴포넌트에서 사용할 수 있는 콘텐츠 컬렉션에 데이터를 로드할 수 있습니다. 내장된 glob()file() 로더는 파일 시스템에서 콘텐츠를 로드하는 데 사용되며, 다른 소스에서 콘텐츠를 로드하기 위한 자체 로더를 만들 수 있습니다.

각 컬렉션에는 스키마에 정의된 로더가 필요합니다. 프로젝트의 src/content.config.ts 파일에서 로더를 인라인으로 정의하거나, 여러 컬렉션 간에 하나의 로더를 공유하거나, 심지어 로더를 NPM 패키지로 게시하여 다른 사람들과 공유하고 통합 라이브러리에 포함시킬 수도 있습니다.

Astro는 컬렉션을 가져오는 데 도움이 되는 두 가지 내장 로더를 제공합니다. 두 로더 모두 다양한 사용 사례에 적합한 옵션을 제공합니다.

타입: (options: GlobOptions) => Loader

Added in: astro@5.0.0

glob() 로더는 파일 시스템의 어디에서나 파일 디렉터리로부터 항목들을 생성합니다. 지원되는 파일 형식은 Markdown, MDX, Markdoc, JSON 및 YAML 파일입니다.

이 로더는 다음과 같은 속성을 가진 객체를 받습니다: pattern, base(선택사항), 그리고 generateId(선택사항).

src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
const pages = defineCollection({
/* pages 디렉터리에 있는 모든 Markdown 파일을 가져옵니다. */
loader: glob({ pattern: "**/*.md", base: "./src/data/pages" }),
schema: /* ... */
});
const blog = defineCollection({
/* blog 디렉터리에 있는 모든 Markdown과 MDX 파일을 가져옵니다. */
loader: glob({ pattern: "**/*.(md|mdx)", base: "./src/data/blog" }),
schema: /* ... */
});
const authors = defineCollection({
/* authors 디렉터리에 있는 모든 JSON 파일을 가져오면서 ID의 대문자를 유지합니다. */
loader: glob({
pattern: '**/*.json',
base: "./src/data/authors",
generateId: ({ entry }) => entry.replace(/\.json$/, ''),
}),
schema: /* ... */
});

타입: string | string[]

pattern 속성은 glob 매칭(예: 와일드카드, 글롭스타)을 사용하는 문자열 또는 문자열 배열을 받습니다. 패턴은 매칭할 엔트리 파일들의 기본 디렉터리를 기준으로 상대 경로여야 합니다.

사용할 수 있는 구문에 대해 더 자세히 알아보려면 micromatch 문서를 참고하세요. 또한 DigitalOcean Glob Tool과 같은 온라인 도구를 사용하여 패턴의 유효성을 확인할 수 있습니다.

타입: string | URL
기본값: "."

pattern을 해석할 때 기준이 되는 디렉터리의 상대 경로 또는 URL입니다.

타입: (options: GenerateIdOptions) => string

컬렉션의 각 항목마다 고유한 문자열을 반환하는 콜백 함수입니다. 이 함수는 다음과 같은 속성들을 가진 객체를 매개변수로 받습니다:

  • entry - 기본 디렉터리를 기준으로 한 항목 파일의 경로
  • base - 기본 디렉터리 URL
  • data - 파싱된, 검증되지 않은 항목 데이터

기본적으로 github-slugger를 사용하여 케밥-케이스 형식의 슬러그를 생성합니다.

타입: (fileName: string, options?: FileOptions) => Loader

Added in: astro@5.0.0

file() 로더는 고유한 id 필드를 가진 객체의 배열 또는 문자열 키를 가진 객체를 포함하는 단일 파일에서 항목을 생성합니다. JSON 또는 YAML을 지원하며, 기본적으로 파싱할 수 없는 데이터 파일을 위해 사용자 정의 parser를 제공할 수 있습니다.

이 로더는 fileName 속성을 받으며, 선택적으로 두 번째 인수로 객체를 받습니다.

src/content.config.ts
import { defineCollection } from 'astro:content';
import { file } from 'astro/loaders';
const authors = defineCollection({
/* JSON 파일에서 모든 항목을 검색합니다. */
loader: file("src/data/authors.json"),
schema: /* ... */
});
const products = defineCollection({
/* 사용자 정의 파서를 사용하여 CSV 파일에서 모든 항목을 검색합니다. */
loader: file("src/data/products.csv", {
parser: (fileContent) => { /* 파서 로직 */ },
}),
schema: /* ... */
});

타입: string

루트 디렉터리를 기준으로 로드할 파일의 경로를 설정합니다.

타입: FileOptions

다음 속성을 가진 선택적 객체입니다:

타입: (text: string) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>>

파일의 콘텐츠에서 컬렉션을 생성하는 콜백 함수입니다. 기본적으로 지원되지 않는 파일(예: .csv)을 처리하거나 중첩된 .json 문서를 사용할 때 사용합니다.

로더는 항목 배열을 반환하는 단순한 함수로 정의하거나, 로딩 프로세스를 더 잘 제어할 수 있는 강력한 객체 콘텐츠 로더 API로 정의할 수 있습니다.

인라인 로더는 항목의 배열이나 객체를 반환하는 비동기 함수입니다. 이것은 특히 src/content.config.ts 파일에 인라인으로 정의된 간단한 로더에 사용하세요.

이 함수는 비동기일 수 있으며 각각 고유한 id 필드를 포함하는 항목의 배열이나, 각 키가 고유 ID이고 각 값이 항목인 객체를 반환해야 합니다. 로더가 호출될 때마다 저장소를 지우고 모든 항목을 다시 로드합니다.

src/content.config.ts
const countries = defineCollection({
loader: async () => {
const response = await fetch("https://restcountries.com/v3.1/all");
const data = await response.json();
// id 속성을 가진 항목의 배열이나
// ID를 키로, 항목을 값으로 가지는 객체를 반환해야 합니다
return data.map((country) => ({
id: country.cca3,
...country,
}));
},
schema: /* ... */
});

로더는 빌드 시점에 데이터를 가져오고 데이터 저장소를 업데이트하기 위해 호출되는 load() 메서드를 가진 객체입니다. 이는 항목을 점진적으로 업데이트하거나 필요한 경우에만 저장소를 지우는 것을 허용합니다. 또한 데이터를 검증하고 정적 타입을 생성하는 데 사용할 수 있는 항목의 스키마를 정의할 수 있습니다.

권장되는 패턴은 Astro 통합이나 Vite 플러그인을 정의하는 것과 같은 방식으로, 구성 옵션을 받아 로더 객체를 반환하는 함수를 정의하는 것입니다.

loader.ts
import type { Loader, LoaderContext } from 'astro/loaders';
import { z } from 'astro:content';
import { loadFeedData } from "./feed.js";
// 로더에 필요한 모든 옵션을 정의
export function myLoader(options: { url: string, apiKey: string }): Loader {
// 로더 구성
const feedUrl = new URL(options.url);
// 로더 객체 반환
return {
name: "my-loader",
// 컬렉션 업데이트 시 호출
load: async (context: LoaderContext): Promise<void> => {
// 데이터 로드 및 저장소 업데이트
const response = await loadFeedData(feedUrl, options.apiKey);
},
// 선택적으로, 항목의 스키마 정의
// 사용자 정의 스키마에 의해 재정의됨
schema: async () => z.object({
// ...
})
};
}

이러한 구성 옵션은 컬렉션을 정의할 때 설정할 수 있습니다:

src/content.config.ts
import { defineCollection, z } from 'astro:content';
import myLoader from '../../loader.ts';
const blog = defineCollection({
loader: myLoader({
url: "https://api.example.com/posts",
apiKey: "my-secret",
}),
schema: /* ... */
});

인라인 로더를 위한 API는 매우 간단하며 위에서 보여드렸습니다. 이 섹션에서는 객체 로더를 정의하기 위한 API를 보여줍니다.

로더 객체는 다음과 같은 속성을 가집니다:

타입: string

로그 및 조건부 로딩에 사용되는 로더의 고유한 이름입니다.

타입: (context: LoaderContext) => Promise<void>

데이터를 로드하고 스토어를 업데이트하기 위해 빌드 시점에 호출되는 비동기 함수입니다. 자세한 내용은 LoaderContext를 참조하세요.

타입: ZodSchema | Promise<ZodSchema> | (() => ZodSchema | Promise<ZodSchema>)

항목의 형태를 정의하는 선택적 Zod 스키마입니다. 이는 데이터를 검증하고 컬렉션에 대한 TypeScript 타입을 생성하는 데 사용됩니다.

함수가 제공되는 경우, 스키마를 생성하기 위해 load() 전 빌드 시점에 호출됩니다. 이를 통해 구성 옵션을 기반으로 하거나 API를 검사하여 스키마를 동적으로 생성할 수 있습니다.

이 객체는 로더의 load() 메서드에 전달되며, 다음과 같은 속성들을 포함합니다:

타입: string

컬렉션의 고유한 이름입니다. 이는 src/content.config.ts 파일의 collections 객체에 있는 키입니다.

타입: DataStore

실제 데이터를 저장하는 데이터베이스입니다. 새로운 항목으로 스토어를 업데이트하기 위해 이를 사용하세요. 자세한 내용은 DataStore를 참조하세요.

타입: MetaStore

동기화 토큰이나 마지막 수정 시간과 같은 항목을 위해 설계된 컬렉션 범위의 키-값 저장소입니다. 이 메타데이터는 컬렉션 데이터와 함께 빌드 간 유지되지만 로더에서만 사용할 수 있습니다.

const lastModified = meta.get("lastModified");
// ...
meta.set("lastModified", new Date().toISOString());

타입: AstroIntegrationLogger

콘솔에 메시지를 로깅하는 데 사용할 수 있는 로거입니다. 로그 메시지에 로더 이름을 포함하는 더 유용한 로그를 위해 console.log 대신 이것을 사용하세요. 자세한 내용은 AstroIntegrationLogger를 참조하세요.

타입: AstroConfig

모든 기본값이 적용된 완전히 해결된 Astro 구성 객체입니다. 자세한 내용은 구성 참조를 확인하세요.

타입: (props: ParseDataOptions<TData>) => Promise<TData>

컬렉션 스키마에 따라 데이터를 검증하고 파싱합니다. 데이터 스토어에 저장하기 전에 데이터를 검증하고 파싱하려면 이 함수에 데이터를 전달하세요.

loader.ts
import type { Loader } from "astro/loaders";
import { loadFeed } from "./feed.js";
export function feedLoader({ url }): Loader {
const feedUrl = new URL(url);
return {
name: "feed-loader",
load: async ({ store, logger, parseData, meta, generateDigest }) => {
logger.info("Loading posts");
const feed = loadFeed(feedUrl);
store.clear();
for (const item of feed.items) {
const data = await parseData({
id: item.guid,
data: item,
});
store.set({
id,
data,
});
}
},
};
}

타입: (data: Record<string, unknown> | string) => string

객체나 문자열의 비암호화 콘텐츠 다이제스트를 생성합니다. 이는 항목의 digest 필드를 설정하여 데이터가 변경되었는지 추적하는 데 사용할 수 있습니다.

loader.ts
import type { Loader } from "astro/loaders";
import { loadFeed } from "./feed.js";
export function feedLoader({ url }): Loader {
const feedUrl = new URL(url);
return {
name: "feed-loader",
load: async ({ store, logger, parseData, meta, generateDigest }) => {
logger.info("Loading posts");
const feed = loadFeed(feedUrl);
store.clear();
for (const item of feed.items) {
const data = await parseData({
id: item.guid,
data: item,
});
const digest = generateDigest(data);
store.set({
id,
data,
digest,
});
}
},
};
}

타입: FSWatcher

개발 모드에서 실행 시, 이는 업데이트를 트리거하는 데 사용할 수 있는 파일시스템 감시자입니다. 자세한 내용은 ViteDevServer를 참조하세요.

Extract from the file() loader
return {
name: 'file-loader',
load: async ({ config, store, watcher }) => {
const url = new URL(fileName, config.root);
const filePath = fileURLToPath(url);
await syncData(filePath, store);
watcher?.on('change', async (changedPath) => {
if (changedPath === filePath) {
logger.info(`Reloading data from ${fileName}`);
await syncData(filePath, store);
}
});
},
};

타입: Record<string, unknown>

로더가 통합에 의해 트리거된 경우, 이는 선택적으로 해당 통합에 의해 설정된 추가 데이터를 포함할 수 있습니다. 이는 로더가 통합에 의해 트리거될 때만 설정됩니다. 자세한 내용은 astro:server:setup 훅 참조를 확인하세요.

loader.ts
export function myLoader(options: { url: string }): Loader {
return {
name: "my-loader",
load: async ({ refreshContextData, store, logger }) => {
if(refreshContextData?.webhookBody) {
logger.info("Webhook triggered with body");
processWebhook(store, refreshContextData.webhookBody);
}
// ...
},
};
}

데이터 스토어는 콘텐츠 컬렉션 데이터에 대한 로더의 인터페이스입니다. 이는 컬렉션 범위의 키-값(KV) 스토어이므로, 로더는 자신의 컬렉션에 대한 데이터에만 접근할 수 있습니다.

타입: (key: string) => DataEntry | undefined

스토어에서 ID로 항목을 가져옵니다. 항목이 존재하지 않는 경우 undefined를 반환합니다.

const existingEntry = store.get("my-entry");

DataEntry 객체를 반환합니다.

타입: (entry: DataEntry) => boolean

데이터가 검증되고 파싱된 후에 스토어에 항목을 추가하는 데 사용되며, 항목이 설정되면 true를 반환합니다. digest 속성이 항목이 변경되지 않았으며 업데이트할 필요가 없다고 판단할 때는 false를 반환합니다.

loader.ts
for (const item of feed.items) {
const data = await parseData({
id: item.guid,
data: item,
});
const digest = generateDigest(data);
store.set({
id,
data,
rendered: {
html: data.description ?? "",
},
digest,
});
}

타입: () => Array<[id: string, DataEntry]>

컬렉션의 모든 항목을 키-값 쌍의 배열로 가져옵니다.

타입: () => Array<string>

컬렉션에 있는 항목의 모든 키를 가져옵니다.

타입: () => Array<DataEntry>

컬렉션의 모든 항목을 배열로 가져옵니다.

타입: (key: string) => void

ID를 사용하여 스토어에서 항목을 삭제합니다.

타입: () => void

컬렉션에서 모든 항목을 삭제합니다.

타입: (key: string) => boolean

ID로 항목이 스토어에 존재하는지 확인합니다.

데이터 스토어에 저장되는 객체의 타입입니다. 다음과 같은 속성을 가집니다:

타입: string

컬렉션에서 고유해야 하는 항목의 식별자입니다. 이는 스토어에서 항목을 찾는 데 사용되며 해당 컬렉션에서 getEntry와 함께 사용되는 키입니다.

타입: Record<string, unknown>

항목의 실제 데이터입니다. 사용자가 컬렉션에 접근할 때, 이는 컬렉션 스키마에 따라 생성된 TypeScript 타입을 가지게 됩니다.

데이터 스토어에 저장하기 전에 parseData를 사용하여 데이터를 검증하고 파싱하는 것은 로더의 책임입니다: 데이터를 가져오거나 설정할 때는 검증이 수행되지 않습니다.

타입: string | undefined

이 항목의 소스가 되는 파일의 경로로, 사이트의 루트를 기준으로 합니다. 이는 파일 기반 로더에만 적용되며 이미지나 다른 자산과 같은 경로를 해결하는 데 사용됩니다.

설정되지 않은 경우, image() 헬퍼를 사용하는 스키마의 모든 필드는 공개 경로로 처리되며 변환되지 않습니다.

타입: string | undefined

해당되는 경우 항목의 원본 본문입니다. 항목이 렌더링된 콘텐츠를 포함하는 경우, 이 필드는 원본 소스를 저장하는 데 사용될 수 있습니다. 이는 선택사항이며 내부적으로 사용되지 않습니다.

타입: string | undefined

항목의 선택적 콘텐츠 다이제스트입니다. 이는 데이터가 변경되었는지 확인하는 데 사용될 수 있습니다.

항목을 설정할 때, 다이제스트가 동일한 ID를 가진 기존 항목과 일치하지 않는 경우에만 항목이 업데이트됩니다.

다이제스트의 형식은 로더에 따라 다르지만, 데이터가 변경될 때 변경되는 문자열이어야 합니다. 이는 generateDigest 함수를 사용하여 수행할 수 있습니다.

타입: RenderedContent | undefined

항목이 HTML로 렌더링된 경우 렌더링된 콘텐츠와 메타데이터가 있는 객체를 저장합니다. 예를 들어, 이는 Markdown 항목의 렌더링된 콘텐츠나 CMS의 HTML을 저장하는 데 사용될 수 있습니다.

이 필드가 제공되면, 페이지에서 항목을 렌더링하기 위해 render() 함수와 <Content /> 컴포넌트를 사용할 수 있습니다.

RenderedContent 객체의 형식은 다음과 같습니다:

{
/** 렌더링된 HTML 문자열입니다. 존재하는 경우 `render(entry)`는 이 HTML을 렌더링하는 컴포넌트를 반환합니다. */
html: string;
metadata?: {
/** 이 항목에 존재하는 모든 이미지입니다. {@link DataEntry} filePath를 기준으로 합니다. */
imagePaths?: Array<string>;
/** 이 파일에 존재하는 모든 제목입니다. `render()`에서 `headings`로 반환됩니다 */
headings?: MarkdownHeading[];
/** 파일에서 파싱된 원본 프런트매터입니다. 이는 remark 플러그인의 데이터를 포함할 수 있습니다. */
frontmatter?: Record<string, any>;
/** 이 파일에 존재하는 다른 모든 메타데이터입니다. */
[key: string]: unknown;
};
}
기여하기 커뮤니티 후원하기
京ICP备15031610号-99