콘텐츠로 이동
This is an unmaintained snapshot of the Astro v5 docs. View the latest docs.

Astro 콘텐츠 로더 API

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

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

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

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

타입: (options: GlobOptions) => Loader

추가된 버전: astro@5.0.0

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

이 로더는 pattern, base(선택사항), generateId(선택사항), retainBody(선택사항) 속성을 가진 객체를 받습니다.

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 notes = defineCollection({
/* notes 디렉터리에 있는 모든 Markdown 파일을 가져오고
콘텐츠 파일의 원본 본문이 데이터 스토어에 저장되지 않도록 합니다. */
loader: glob({
pattern: '**/*.md',
base: './src/data/notes',
retainBody: false
}),
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를 사용하여 케밥-케이스 형식의 슬러그를 생성합니다.

타입: boolean
기본값: true

추가된 버전: astro@5.17.0

콘텐츠 파일의 원본 본문을 데이터 스토어에 저장할지 여부입니다.

retainBodyfalse일 때, entry.body는 원본 파일 콘텐츠를 포함하는 대신 undefined가 됩니다.

이 속성을 false로 설정하면 데이터 스토어의 배포 크기를 크게 감소시켜 매우 큰 컬렉션을 가진 사이트에서 크기 제한에 도달하는 것을 방지하는 데 도움이 됩니다.

Markdown 파일의 경우, 렌더링된 본문은 여전히 entry.rendered.html 속성에서 사용할 수 있으며, entry.filePath 속성은 여전히 원본 파일을 가리킵니다.

MDX 컬렉션의 경우, 스토어에 본문이 더 이상 유지되지 않으므로 컬렉션의 크기가 크게 줄어들 것입니다.

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

추가된 버전: astro@5.0.0

file() 로더는 고유한 id 필드를 가진 객체의 배열을 포함하는 단일 파일 또는 ID를 키로, 항목을 값으로 가지는 객체로부터 항목을 생성합니다. JSON, YAML 또는 TOML 파일을 지원하며, 기본적으로 파싱할 수 없는 데이터 파일을 위해 사용자 정의 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>> | Promise<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/zod';
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 } from 'astro:content';
import { z } from 'astro/zod';
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,
});
}
},
};
}

타입: (markdown: string) => Promise<RenderedContent>

추가된 버전: astro@5.9.0

RenderedContent 객체를 반환하면서 Markdown 문자열을 HTML로 렌더링합니다.

이 기능을 사용하면 Astro의 내장 glob 로더와 동일한 Markdown 처리 방식을 사용하여 로더에서 Markdown 콘텐츠를 직접 렌더링할 수 있습니다. 또한 본문 콘텐츠를 렌더링하기 위한 render() 함수와 <Content /> 컴포넌트에 접근할 수도 있습니다.

사용자가 페이지에서 콘텐츠를 렌더링할 수 있도록 이 객체를 DataEntry 객체의 rendered 필드에 할당하세요.

loader.ts
import type { Loader } from 'astro/loaders';
import { loadFromCMS } from './cms.js';
export function myLoader(settings): Loader {
return {
name: 'cms-loader',
async load({ renderMarkdown, store }) {
const entries = await loadFromCMS();
store.clear();
for (const entry of entries) {
store.set({
id: entry.id,
data: entry,
// 각 항목에 Markdown 콘텐츠를 나타내는 'content' 필드가 있다고 가정합니다.
rendered: await renderMarkdown(entry.content),
});
}
},
};
}

타입: (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?: {
/** 이 항목에 존재하는 모든 이미지입니다. DataEntry의 filePath를 기준으로 합니다. */
imagePaths?: Array<string>;
/** 이 파일에 존재하는 모든 제목입니다. `render()`에서 `headings`로 반환됩니다 */
headings?: MarkdownHeading[];
/** 파일에서 파싱된 원본 프런트매터입니다. 이는 remark 플러그인의 데이터를 포함할 수 있습니다. */
frontmatter?: Record<string, any>;
/** 이 파일에 존재하는 다른 모든 메타데이터입니다. */
[key: string]: unknown;
};
}

항목에 Markdown 콘텐츠가 있는 경우 renderMarkdown() 함수를 사용하여 Markdown 문자열에서 이 객체를 생성할 수 있습니다.

기여하기 커뮤니티 후원하기