콘텐츠 컬렉션
Added in:
astro@2.0.0
콘텐츠 컬렉션은 모든 Astro 프로젝트에서 콘텐츠 세트를 관리하는 가장 좋은 방법입니다. 컬렉션은 문서를 구성 및 쿼리하고, 편집기에서 자동 완성 및 타입 검사를 활성화하고, 모든 콘텐츠에 대해 TypeScript 타입 안전성을 제공하는 데 도움이 됩니다. Astro v5.0에서는 콘텐츠 컬렉션을 정의하고 쿼리하기 위한 Content Layer API가 도입되었습니다. 이 확장 가능한 고성능 API는 로컬 컬렉션을 위한 내장 콘텐츠 로더를 제공합니다. 원격 콘텐츠의 경우 타사 및 커뮤니티에서 구축한 로더를 사용하거나 자체 사용자 지정 로더를 만들어 모든 소스에서 데이터를 가져올 수 있습니다.
프로젝트는 Astro v2.0에 도입된 레거시 콘텐츠 컬렉션 API를 계속 사용할 수 있습니다. 그러나 가능하면 기존 컬렉션을 업데이트하는 것이 좋습니다.
콘텐츠 컬렉션이란 무엇입니까?
섹션 제목: 콘텐츠 컬렉션이란 무엇입니까?구조적으로 유사한 데이터 집합에서 컬렉션을 정의할 수 있습니다. 블로그 게시물의 디렉터리, 제품 항목의 JSON 파일 또는 동일한 모양의 여러 항목을 나타내는 모든 데이터가 여기에 해당할 수 있습니다.
프로젝트 또는 파일 시스템에 로컬로 저장된 컬렉션에는 Markdown, MDX, Markdoc 또는 JSON 파일 항목이 있을 수 있습니다:
디렉터리src/
- …
디렉터리newsletter/ “newsletter” 컬렉션
- week-1.md 컬렉션 항목
- week-2.md 컬렉션 항목
- week-3.md 컬렉션 항목
디렉터리authors/ “author” 컬렉션
- authors.json 모든 컬렉션 항목이 포함된 단일 파일
적절한 컬렉션 로더를 사용하면 CMS, 데이터베이스, 헤드리스 결제 시스템 등 모든 외부 소스에서 원격 데이터를 가져올 수 있습니다.
컬렉션을 위한 TypeScript 구성
섹션 제목: 컬렉션을 위한 TypeScript 구성콘텐츠 컬렉션은 편집기에서 Zod 유효성 검사, 자동 완성 및 타입 검사를 제공하기 위해 TypeScript에 의존합니다. Astro의 TypeScript 설정을 strict
또는 strictest
중 하나로 확장하지 않는 경우 tsconfig.json
에 다음 compilerOptions
이 설정되어 있는지 확인해야 합니다:
컬렉션 정의
섹션 제목: 컬렉션 정의개별 컬렉션은 defineCollection()
을 사용하여 구성합니다:
- 데이터 소스를 위한
loader
(필수) - 타입 안전을 위한
schema
(선택 사항이지만 적극 권장!)
컬렉션 구성 파일
섹션 제목: 컬렉션 구성 파일컬렉션을 정의하려면 프로젝트에 src/content.config.ts
파일을 만들어야 합니다(.js
및 .mjs
확장자도 지원됨). 이 파일은 Astro가 다음 구조에 따라 콘텐츠 컬렉션을 구성하는 데 사용하는 특수 파일입니다:
컬렉션 loader
정의
섹션 제목: 컬렉션 loader 정의Content Layer API를 사용하면 프로젝트에 로컬로 저장하든 원격으로 저장하든 콘텐츠를 가져올 수 있으며, loader
속성을 사용하여 데이터를 검색할 수 있습니다.
내장 로더
섹션 제목: 내장 로더Astro는 로컬 콘텐츠를 가져오기 위한 두 가지 내장 로더 함수(glob()
및 file()
)와 자체 로더를 구성하고 원격 데이터를 가져오기 위한 API에 대한 액세스를 제공합니다.
glob()
로더는 파일 시스템 어디에서나 Markdown, MDX, Markdoc 또는 JSON 파일 디렉터리에서 항목을 만듭니다. 일치시킬 항목 파일의 pattern
과 파일이 있는 위치의 base
파일 경로를 인자로 받습니다. 각 항목의 id
는 파일 이름으로부터 자동으로 생성됩니다. 항목당 파일이 하나씩 있을 때 이 로더를 사용합니다.
file()
로더는 단일 로컬 파일에서 여러 항목을 생성합니다. 파일의 각 항목에는 고유한 id
키 속성이 있어야 합니다. 이 로더는 파일의 base
파일 경로를 인자로 받고 자동으로 분석할 수 없는 파일을 위해 선택적으로 parser
함수를 인자로 받습니다. 데이터 파일을 객체 배열로 구문 분석할 수 있는 경우 이 로더를 사용합니다.
parser
함수
섹션 제목: parser 함수file()
로더는 parser
함수를 정의하는 두 번째 인수를 받습니다. 이를 통해 사용자 정의 구문 분석기(예: toml.parse
또는 csv-parse
)를 지정하여 파일 콘텐츠에서 컬렉션을 생성할 수 있습니다.
file()
로더는 중첩된 JSON 문서가 없는 한 parser
가 필요 없이 JSON 및 YAML 파일에서(파일 확장자에 따라) 단일 객체 배열을 자동으로 감지하고 구문 분석합니다. .toml
및 .csv
와 같은 다른 파일을 사용하려면 파서 함수를 만들어야 합니다.
다음 예시에서는 .toml
파일을 사용하여 콘텐츠 컬렉션 dogs
를 정의합니다:
TOML의 파서를 가져온 후 파일 경로와 parser
함수를 모두 file()
로더에 전달하여 dogs
컬렉션을 프로젝트에 로드할 수 있습니다. 비슷한 과정을 통해 .csv
파일에서 cats
컬렉션을 정의할 수 있습니다:
중첩된 .json
문서
섹션 제목: 중첩된 .json 문서parser
인수를 사용하면 중첩된 JSON 문서에서 단일 컬렉션을 로드할 수도 있습니다. 예를 들어 이 JSON 파일에는 여러 컬렉션이 포함되어 있습니다:
각 컬렉션에 대해 사용자 정의 parser
를 file()
로더에 전달하여 이러한 컬렉션을 분리할 수 있습니다:
사용자 지정 로더 빌드
섹션 제목: 사용자 지정 로더 빌드사용자 지정 로더를 빌드하여 CMS, 데이터베이스, API 엔드포인트 등 모든 데이터 소스에서 원격 콘텐츠를 가져올 수 있습니다.
로더를 사용해 데이터를 가져오면 원격 데이터에서 컬렉션이 자동으로 만들어집니다. 이렇게 하면 getCollection()
및 render()
와 같이 데이터를 쿼리하고 표시하는 컬렉션 전용 API 헬퍼와 스키마 유효성 검사 등 로컬 컬렉션의 모든 이점을 누릴 수 있습니다.
Astro 통합 디렉터리에서 커뮤니티 구축 및 타사 로더를 찾아보세요.
인라인 로더
섹션 제목: 인라인 로더컬렉션 내부에서 로더를 인라인으로 정의하여 항목 배열을 반환하는 비동기 함수로 정의할 수 있습니다.
이는 데이터를 불러와 저장하는 방식을 수동으로 제어할 필요가 없는 로더에 유용합니다. 로더가 호출될 때마다 스토어를 비우고 모든 항목을 다시 불러옵니다.
반환된 항목들은 컬렉션에 저장되며 getCollection()
및 getEntry()
함수를 사용하여 조회할 수 있습니다.
로더 객체
섹션 제목: 로더 객체로딩 프로세스를 더 세밀하게 제어하려면 Content Loader API를 사용하여 로더 객체를 생성할 수 있습니다. 예를 들어, load
메서드에 직접 접근할 수 있어 항목을 점진적으로 업데이트하거나 필요할 때만 스토어를 비우는 로더를 만들 수 있습니다.
Astro 통합이나 Vite 플러그인을 만드는 것처럼, 로더를 NPM 패키지로 배포하여 다른 사람들이 자신의 프로젝트에서 사용할 수 있게 할 수 있습니다.
컬렉션 스키마 정의
섹션 제목: 컬렉션 스키마 정의스키마는 Zod 유효성 검사를 통해 컬렉션의 프런트매터나 항목 데이터의 일관성을 강제합니다. 스키마는 데이터를 참조하거나 쿼리할 때 데이터가 예측 가능한 형태로 존재함을 보장합니다. 만약 어떤 파일이 컬렉션 스키마를 위반하면, Astro는 도움이 되는 오류 메시지를 표시합니다.
스키마는 또한 Astro의 자동 TypeScript 타입 생성 기능을 제공합니다. 컬렉션에 스키마를 정의하면 Astro는 자동으로 TypeScript 인터페이스를 생성하고 적용합니다. 그 결과 컬렉션을 쿼리할 때 속성 자동 완성과 타입 검사를 포함한 완전한 TypeScript 지원을 받을 수 있습니다.
컬렉션 항목의 모든 프런트매터나 데이터 속성은 Zod 데이터 타입을 사용하여 정의되어야 합니다:
Zod를 사용한 데이터 타입 정의
섹션 제목: Zod를 사용한 데이터 타입 정의Astro는 콘텐츠 스키마를 위해 Zod를 사용합니다. Astro는 Zod를 통해 컬렉션의 모든 파일의 데이터를 검증하고, 프로젝트에서 콘텐츠를 쿼리할 때 자동으로 TypeScript 타입을 제공할 수 있습니다.
Astro에서 Zod를 사용하려면 "astro:content"
에서 z
유틸리티를 가져옵니다. 이는 Zod 라이브러리를 다시 내보낸 것으로, Zod의 모든 기능을 지원합니다.
Zod 스키마 메서드
섹션 제목: Zod 스키마 메서드모든 Zod 스키마 메서드(예: .parse()
, .transform()
)는 일부 제한사항과 함께 사용할 수 있습니다. 특히 image().refine()
을 사용한 이미지의 사용자 정의 유효성 검사는 지원되지 않습니다.
컬렉션 참조 정의
섹션 제목: 컬렉션 참조 정의컬렉션 항목은 다른 관련 항목을 “참조”할 수도 있습니다.
Collections API의 reference()
함수를 사용하면 컬렉션 스키마의 속성을 다른 컬렉션의 항목으로 정의할 수 있습니다. 예를 들어, 모든 space-shuttle
항목에 pilot
컬렉션의 스키마를 사용하여 타입 검사, 자동 완성, 유효성 검증을 수행하는 pilot
속성을 포함하도록 요구할 수 있습니다.
일반적인 예시로는 JSON으로 저장된 재사용 가능한 작성자 프로필을 참조하거나, 같은 컬렉션에 저장된 관련 게시물 URL을 참조하는 블로그 게시물이 있습니다:
이 예시 블로그 게시물은 관련 게시물들의 id
와 게시물 작성자의 id
를 지정합니다:
사용자 지정 ID 정의
섹션 제목: 사용자 지정 ID 정의Markdown, MDX, Markdoc 또는 JSON 파일에 glob()
로더를 사용할 때, 모든 콘텐츠 항목의 id
는 콘텐츠 파일 이름을 기반으로 URL 친화적인 형식으로 자동 생성됩니다. 이 id
는 컬렉션에서 직접 항목을 쿼리할 때 사용됩니다. 또한 콘텐츠로부터 새로운 페이지와 URL을 만들 때도 유용합니다.
파일의 프런트매터나 JSON 파일의 데이터 객체에 slug
속성을 추가하여 항목의 자동 생성된 id
를 재정의할 수 있습니다. 이는 다른 웹 프레임워크의 “permalink” 기능과 유사합니다.
컬렉션 쿼리
섹션 제목: 컬렉션 쿼리Astro는 컬렉션을 쿼리하고 하나 (또는 여러 개)의 콘텐츠 항목을 반환하는 헬퍼 함수를 제공합니다.
getCollection()
은 전체 컬렉션을 가져와서 항목 배열을 반환합니다.getEntry()
는 컬렉션에서 단일 항목을 가져옵니다.
이들은 고유한 id
, 정의된 모든 속성을 포함한 data
객체, 그리고 Markdown, MDX 또는 Markdoc 문서의 컴파일되지 않은 원시 본문을 포함하는 body
를 가진 항목들을 반환합니다.
CollectionEntry
타입이 반환하는 전체 속성 목록을 확인하세요.
Astro 템플릿에서 콘텐츠 사용
섹션 제목: Astro 템플릿에서 콘텐츠 사용컬렉션을 쿼리한 후에는 Astro 컴포넌트 템플릿에서 각 항목의 콘텐츠에 직접 접근할 수 있습니다. 예를 들어, data
속성을 사용하여 항목의 프런트매터 정보를 표시하는 블로그 게시물 링크 목록을 만들 수 있습니다.
본문 콘텐츠 렌더링
섹션 제목: 본문 콘텐츠 렌더링쿼리가 완료되면 render()
함수 속성을 사용하여 Markdown과 MDX 항목을 HTML로 렌더링할 수 있습니다. 이 함수를 호출하면 <Content />
컴포넌트와 렌더링된 모든 제목 목록을 포함한 HTML 콘텐츠에 접근할 수 있습니다.
콘텐츠를 props로 전달
섹션 제목: 콘텐츠를 props로 전달컴포넌트는 컬렉션 항목 전체를 prop으로 전달할 수도 있습니다.
TypeScript를 사용하여 컴포넌트의 props를 올바르게 타이핑하기 위해 CollectionEntry
유틸리티를 사용할 수 있습니다. 이 유틸리티는 컬렉션 스키마의 이름과 일치하는 문자열 인자를 받아 해당 컬렉션 스키마의 모든 속성을 상속합니다.
컬렉션 쿼리 필터링
섹션 제목: 컬렉션 쿼리 필터링getCollection()
은 항목의 id
나 data
속성을 기반으로 쿼리를 필터링할 수 있는 선택적 “filter” 콜백을 받습니다.
이를 통해 원하는 모든 콘텐츠 조건으로 필터링할 수 있습니다. 예를 들어, draft
같은 속성으로 필터링하여 초안 상태인 블로그 게시물이 게시되는 것을 방지할 수 있습니다:
개발 환경에서는 접근 가능하지만 프로덕션 빌드에서는 제외되는 초안 페이지를 만들 수 있습니다:
필터 인자는 컬렉션 내에서 중첩된 디렉터리로도 필터링을 할 수 있습니다. id
가 전체 중첩 경로를 포함하고 있기 때문에, 각 id
의 시작 부분으로 필터링하여 특정 중첩 디렉터리의 항목만 반환할 수 있습니다:
참조된 데이터에 액세스
섹션 제목: 참조된 데이터에 액세스스키마에 정의된 모든 참조는 컬렉션 항목을 먼저 쿼리한 후 별도로 쿼리해야 합니다. getEntry()
함수를 사용하여 단일 참조 항목을 반환하거나, getEntries()
를 사용하여 반환된 data 객체에서 여러 참조 항목을 가져올 수 있습니다.
콘텐츠로부터 라우트 생성
섹션 제목: 콘텐츠로부터 라우트 생성콘텐츠 컬렉션은 src/pages/
디렉터리 외부에 저장됩니다. 이는 기본적으로 컬렉션 항목에 대한 페이지나 라우트가 생성되지 않는다는 것을 의미합니다.
개별 블로그 게시물과 같이 각 컬렉션 항목에 대한 HTML 페이지를 생성하려면 새로운 동적 라우트를 수동으로 생성해야 합니다. 동적 라우트는 들어오는 요청 매개변수(예: src/pages/blog/[...slug].astro
의 Astro.params.slug
)를 각 페이지에 맞는 올바른 항목을 가져오는 데 사용합니다.
라우트 생성을 위한 정확한 방법은 페이지가 미리 렌더링되는지(기본값) 또는 서버에서 필요할 때 렌더링되는지에 따라 달라집니다.
정적 출력을 위한 빌드(기본값)
섹션 제목: 정적 출력을 위한 빌드(기본값)정적 웹사이트를 빌드하는 경우(Astro의 기본 동작), 빌드 시 단일 페이지 컴포넌트(예: src/pages/[slug]
)에서 여러 페이지를 생성하기 위해 getStaticPaths()
함수를 사용하세요.
getStaticPaths()
에서 getCollection()
을 호출하여 정적 라우트 빌드에 필요한 컬렉션 데이터를 사용할 수 있습니다. 그런 다음 각 콘텐츠 항목의 id
속성을 사용하여 개별 URL 경로를 생성합니다. 각 페이지는 전체 컬렉션 항목을 prop으로 전달받아 페이지 템플릿에서 사용할 수 있습니다.
blog
컬렉션의 모든 항목에 대해 페이지 라우트가 생성됩니다. 예를 들어, src/blog/hello-world.md
에 있는 항목의 id
는 hello-world
가 되며, 따라서 최종 URL은 /posts/hello-world/
가 됩니다.
/
문자가 포함된 커스텀 슬러그를 사용하여 여러 경로 세그먼트가 있는 URL을 생성하는 경우, 이 동적 라우팅 페이지의 .astro
파일 이름에 나머지 매개변수(예: [...slug]
)를 사용해야 합니다.
서버 출력(SSR) 빌드
섹션 제목: 서버 출력(SSR) 빌드동적 웹사이트를 만드는 경우(Astro의 SSR 지원 사용), 빌드 과정에서 경로를 미리 생성할 필요가 없습니다. 대신, 페이지에서 요청을 검사하여(Astro.request
또는 Astro.params
사용) slug
를 찾은 다음 getEntry()
를 사용하여 가져오면 됩니다.
GitHub의 블로그 튜토리얼 데모 코드의 src/pages/
폴더를 살펴보면 블로그 게시물 목록, 태그 페이지 등과 같은 블로그 기능을 위해 컬렉션으로부터 페이지를 생성하는 전체 예시를 확인할 수 있습니다!
컬렉션 생성이 필요한 경우
섹션 제목: 컬렉션 생성이 필요한 경우관련된 데이터나 콘텐츠가 공통 구조를 공유하는 그룹이 있을 때마다 컬렉션을 생성할 수 있습니다.
컬렉션 사용의 주요 이점은 다음과 같습니다:
- 개별 항목이 “올바른지” 또는 “완전한지” 검증하여 프로덕션에서의 오류를 방지할 수 있는 공통 데이터 형태를 정의할 수 있습니다.
- 페이지에서 콘텐츠를 가져와 렌더링할 때 직관적인 쿼리가 가능하도록 설계된 콘텐츠 중심의 API를 제공합니다(예:
import.meta.glob()
대신getCollection()
사용). - 콘텐츠를 가져오기 위한 Content Loader API는 내장 로더와 저수준 API 접근을 모두 제공합니다. 여러 서드파티 및 커뮤니티에서 제작한 로더를 사용할 수 있으며, 원하는 곳에서 데이터를 가져올 수 있는 자체 커스텀 로더를 만들 수도 있습니다.
- 성능과 확장성이 뛰어납니다. Content Layer API를 통해 빌드 간에 데이터를 캐시할 수 있으며, 수만 개의 콘텐츠 항목도 처리할 수 있습니다.
다음과 같은 경우에 데이터를 컬렉션으로 정의하세요:
- 동일한 구조(예: 같은 프런트매터 속성을 가진 Markdown 블로그 게시물들)를 공유하는 여러 파일이나 데이터를 정리해야 하는 경우
- CMS와 같이 원격에 저장된 기존 콘텐츠가 있고,
fetch()
나 SDK 대신 컬렉션 헬퍼 함수와 Content Layer API를 활용하고 싶은 경우 - 수만 개의 연관된 데이터를 가져와야 하고, 대규모 처리가 가능한 쿼리와 캐싱 방법이 필요한 경우
컬렉션 생성이 불필요한 경우
섹션 제목: 컬렉션 생성이 불필요한 경우컬렉션은 동일한 속성을 공유해야 하는 여러 콘텐츠가 있을 때 우수한 구조와 안정성, 그리고 체계를 제공합니다.
다음과 같은 경우에는 컬렉션이 적절한 해결책이 아닐 수 있습니다:
- 하나 또는 소수의 서로 다른 페이지만 있는 경우. 대신
src/pages/about.astro
와 같이 콘텐츠를 직접 포함하는 개별 페이지 컴포넌트를 만드는 것을 고려하세요. - PDF와 같이 Astro가 처리하지 않는 파일을 표시하는 경우. 대신 이러한 정적 자산을 프로젝트의
public/
디렉터리에 두세요. - 데이터 소스가 가져오기를 위한 자체 SDK/클라이언트 라이브러리를 보유하고 있으며, 이 라이브러리가 콘텐츠 로더와 호환되지 않거나 콘텐츠 로더를 제공하지 않아 해당 라이브러리를 직접 사용하는 것을 선호하는 경우
- 실시간으로 업데이트가 필요한 API를 사용하고 있는 경우. 콘텐츠 컬렉션은 빌드 시에만 업데이트되므로, 실시간 데이터가 필요한 경우에는 요청 시 렌더링을 통해 파일 가져오기 또는 데이터 가져오기와 같은 다른 방법을 사용하세요.