컨텐츠로 건너뛰기

Astro에서 Markdown 사용하기

Markdown은 일반적으로 블로그 게시물 및 문서와 같이 텍스트가 많은 콘텐츠를 작성하는 데 사용됩니다. Astro에는 title, description, tags와 같은 사용자 정의 속성을 정의하기 위해 프런트매터 YAML도 포함할 수 있는 Markdown 파일에 대한 기본 지원이 포함되어 있습니다.

Astro에서는 GitHub Flavored Markdown으로 콘텐츠를 작성한 다음 .astro 컴포넌트에 이를 렌더링할 수 있습니다. 이는 콘텐츠용으로 설계된 친숙한 작성 형식과 Astro의 컴포넌트 구문 및 아키텍처의 유연성을 결합한 것입니다.

로컬 Markdown 파일은 src/ 디렉터리 내 어디에나 보관할 수 있습니다. 단일 로컬 Markdown 파일은 import 문을 사용하여 .astro 컴포넌트로 가져올 수 있으며, 여러 파일을 한 번에 쿼리하기 위해서는 Vite의 import.meta.glob()을 사용할 수 있습니다.

연관된 Markdown 파일 그룹이 있는 경우 컬렉션으로 정의하는 것을 고려해 보세요. 이렇게 하면 파일 시스템의 어느 곳에나 또는 원격으로 Markdown 파일을 저장할 수 있는 등 여러 가지 이점이 있습니다.

컬렉션을 사용하면 콘텐츠별로 최적화된 API를 사용하여 콘텐츠를 쿼리하고 렌더링할 수도 있습니다. 컬렉션은 블로그 게시물이나 제품 항목과 같이 동일한 구조를 공유하는 데이터 집합을 위한 것입니다. 스키마에서 해당 형태를 정의하면 편집기에서 유효성 검사, 타입 안전, 인텔리센스를 사용할 수 있습니다.

Markdown 파일을 가져오거나 쿼리한 후에는 프런트매터 데이터와 본문 콘텐츠를 포함하는 .astro 컴포넌트에 동적 HTML 템플릿을 작성할 수 있습니다.

src/posts/great-post.md
---
title: 'The greatest post of all time'
author: 'Ben'
---
Here is my _great_ post!
src/pages/my-posts.astro
---
import * as greatPost from '../posts/great-post.md';
const posts = Object.values(await import.meta.glob('../posts/*.md', { eager: true }));
---
<p>{greatPost.frontmatter.title}</p>
<p>Written by: {greatPost.frontmatter.author}</p>
<p>Post Archive:</p>
<ul>
{posts.map(post => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
</ul>

도우미 함수를 통해 컬렉션에서 데이터를 가져올 때 Markdown의 frontmatter 속성은 data 객체 (예: post.data.title)에서 사용할 수 있습니다. 또한 body에는 컴파일되지 않은 원시 본문 콘텐츠가 문자열로 포함됩니다.

CollectionEntry 타입에 대해 알아보세요.

import 또는 import.meta.glob()을 사용하여 Markdown을 가져올 때 내보낸 다음 속성은 .astro 컴포넌트에서 사용할 수 있습니다:

  • file - 절대 파일 경로 (예: /home/user/projects/.../file.md).
  • url - 페이지의 URL (예: /en/guides/markdown-content).
  • frontmatter - 파일의 YAML 프런트매터에 지정된 모든 데이터를 포함합니다.
  • <Content /> - 파일의 전체 렌더링된 콘텐츠를 반환하는 컴포넌트입니다.
  • rawContent() - 원시 Markdown 문서를 문자열로 반환하는 함수입니다.
  • compiledContent() - HTML 문자열로 컴파일된 Markdown 문서를 반환하는 함수입니다.
  • getHeadings() - { depth: number; slug: string; text: string }[] 타입을 가지는 파일의 모든 제목 (예: <h1>부터 <h6>)의 배열을 반환하는 비동기 함수입니다. 각 제목의 slug는 특정 제목에 대해 생성된 ID에 해당하며, 앵커 링크에 사용될 수 있습니다.

Markdown 블로그 게시물 예시에서는 다음 Astro.props 객체를 전달할 수 있습니다:

Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** 블로그 게시물의 프런트매터 */
title: "Astro 0.18 Release",
date: "Tuesday, July 27 2021",
author: "Matthew Phillips",
description: "Astro 0.18 is our biggest release since Astro launch.",
},
getHeadings: () => [
{"depth": 1, "text": "Astro 0.18 Release", "slug": "astro-018-release"},
{"depth": 2, "text": "Responsive partial hydration", "slug": "responsive-partial-hydration"}
/* ... */
],
rawContent: () => "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]",
compiledContent: () => "<h1>Astro 0.18 Release</h1>\n<p>A little over a month ago, the first public beta [...]</p>",
}

<Content /> 컴포넌트는 Markdown 파일에서 Content를 가져와서 사용할 수 있습니다. 이 컴포넌트는 파일의 전체 본문 콘텐츠를 HTML로 렌더링하여 반환합니다. 선택적으로 Content의 이름을 원하는 컴포넌트 이름으로 변경할 수 있습니다.

이와 유사하게 <Content /> 컴포넌트를 렌더링하여 Markdown 컬렉션 항목의 HTML 콘텐츠를 렌더링을 할 수 있습니다.

src/pages/content.astro
---
// 가져오기 문
import {Content as PromoBanner} from '../components/promoBanner.md';
// 컬렉션 쿼리
import { getEntry, render } from 'astro:content';
const product = await getEntry('products', 'shirt');
const { Content } = await render();
---
<h2>Today's promo</h2>
<PromoBanner />
<p>Sale Ends: {product.data.saleEndDate.toDateString()}</p>
<Content />

Markdown으로 제목을 작성하면 자동으로 앵커 링크가 제공되므로 페이지의 특정 섹션으로 바로 연결할 수 있습니다.

src/pages/page-1.md
---
title: My page of content
---
## Introduction
I can link internally to [my conclusion](#conclusion) on the same page when writing Markdown.
## Conclusion
I can visit `https://example.com/page-1/#introduction` in a browser to navigate directly to my Introduction.

Astro는 github-slugger를 기반으로 제목의 id를 생성합니다. 더 많은 예시는 github-slugger 문서에서 찾을 수 있습니다.

Astro는 Markdown 및 MDX 파일의 모든 제목 요소 (<h1> ~ <h6>)에 id 속성을 삽입하고 Markdown 내보낸 속성에서 이러한 ID를 검색하기 위한 getHeadings() 유틸리티를 제공합니다.

id 속성 (예: rehype-slug)을 삽입하는 rehype 플러그인을 추가하여 이러한 제목 ID를 맞춤설정할 수 있습니다. Astro의 기본값 대신 사용자 정의 ID가 HTML 출력과 getHeadings()에 의해 반환된 항목에 반영됩니다.

기본적으로 Astro는 rehype 플러그인이 실행된 후 id 속성을 주입합니다. 사용자 정의 rehype 플러그인 중 하나가 Astro에서 삽입한 ID에 액세스해야 하는 경우 Astro의 rehypeHeadingIds 플러그인을 직접 가져와 사용할 수 있습니다. 이를 사용하는 플러그인 앞에 rehypeHeadingIds를 추가하세요.

astro.config.mjs
import { defineConfig } from 'astro/config';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import { otherPluginThatReliesOnHeadingIDs } from 'some/plugin/source';
export default defineConfig({
markdown: {
rehypePlugins: [
rehypeHeadingIds,
otherPluginThatReliesOnHeadingIDs,
],
},
});

Astro의 Markdown 지원은 활성 생태계를 갖춘 강력한 구문 분석 및 처리 도구인 remark를 통해 제공됩니다. Pandoc 및 markdown-it과 같은 다른 Markdown 파서는 현재 지원되지 않습니다.

Astro는 기본적으로 GitHub-flavored MarkdownSmartyPants 플러그인을 적용합니다. 이는 텍스트에서 클릭 가능한 링크 생성, 인용 및 em-dashes 서식 지정과 같은 몇 가지 장점을 제공합니다.

astro.config.mjs 파일에서 remark가 Markdown을 구문 분석하는 방법을 사용자 정의할 수 있습니다. Markdown 구성 옵션의 전체 목록을 확인하세요.

remark 및 rehype 플러그인 추가하기

섹션 제목: remark 및 rehype 플러그인 추가하기

Astro는 Markdown에 대한 타사 remarkrehype 플러그인 추가를 지원합니다. 이러한 플러그인을 사용하면 목차 자동 생성, 접근 가능한 이모티콘 라벨 적용, Markdown 스타일 지정과 같은 새로운 기능으로 Markdown을 확장할 수 있습니다.

awesome-remarkawesome-rehype와 같은 인기 플러그인들을 찾아보시기 바랍니다! 구체적인 설치 지침은 각 플러그인의 자체 README를 참조하세요.

이 예시에서는 Markdown 파일에 remark-tocrehype-accessible-emojis를 적용합니다.

astro.config.mjs
import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';
import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';
export default defineConfig({
markdown: {
// .md 및 .mdx 파일에 적용됨
remarkPlugins: [ [remarkToc, { heading: 'toc', maxDepth: 3 } ] ],
rehypePlugins: [rehypeAccessibleEmojis],
},
});

플러그인을 사용자 정의하려면 중첩 배열에서 플러그인 뒤에 옵션 객체를 제공하세요.

아래 예시에서는 remarkToc 플러그인에 heading 옵션을 추가하여 목차 위치를 변경하고, rehype-autolink-headings 플러그인에 behavior 옵션을 추가하여 제목 텍스트 뒤에 앵커 태그를 추가했습니다.

astro.config.mjs
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default {
markdown: {
remarkPlugins: [ [remarkToc, { heading: "contents"} ] ],
rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }]],
},
}

프로그래밍 방식으로 프런트매터 수정하기

섹션 제목: 프로그래밍 방식으로 프런트매터 수정하기

remark 또는 rehype 플러그인을 사용하여 모든 Markdown 및 MDX 파일에 프런트매터 속성을 추가할 수 있습니다.

  1. 플러그인의 file 인수에서 data.astro.frontmatter 속성에 customProperty를 추가합니다.

    example-remark-plugin.mjs
    export function exampleRemarkPlugin() {
    // 모든 remark 및 rehype 플러그인은 별도의 함수를 반환합니다.
    return function (tree, file) {
    file.data.astro.frontmatter.customProperty = 'Generated property';
    }
    }
  2. 이 플러그인을 markdown 또는 mdx 통합 구성에 적용하세요.

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';
    export default defineConfig({
    markdown: {
    remarkPlugins: [exampleRemarkPlugin]
    },
    });

    또는

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';
    export default defineConfig({
    integrations: [
    mdx({
    remarkPlugins: [exampleRemarkPlugin],
    }),
    ],
    });

이제 모든 Markdown 또는 MDX 파일의 프런트매터에 customProperty가 있으므로 Markdown을 가져올 때 레이아웃의 Astro.props.frontmatter 속성에서 사용할 수 있습니다.

관련 레시피: 읽기 시간 추가

MDX에서 Markdown 구성 확장

섹션 제목: MDX에서 Markdown 구성 확장

Astro의 MDX 통합은 기본적으로 프로젝트의 기존 Markdown 구성을 확장합니다. 개별 옵션을 재정의하려면 MDX 구성에서 해당 옵션을 지정하면 됩니다.

다음 예시에서는 GitHub 기반 Markdown을 비활성화하고 MDX 파일에 대해 다른 remark 플러그인 세트를 적용합니다.

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
syntaxHighlight: 'prism',
remarkPlugins: [remarkPlugin1],
gfm: true,
},
integrations: [
mdx({
// Markdown에서 상속된 `syntaxHighlight`
// Markdown `remarkPlugins`가 무시되었습니다.
// `remarkPlugin2`만 적용됩니다.
remarkPlugins: [remarkPlugin2],
// `gfm`이 `false`로 재정의됨
gfm: false,
})
]
});

MDX에서 Markdown 구성을 확장하지 않으려면 extendMarkdownConfig 옵션 (기본적으로 활성화됨)을 false로 설정하세요.

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
remarkPlugins: [remarkPlugin],
},
integrations: [
mdx({
// Markdown 구성은 이제 무시됩니다.
extendMarkdownConfig: false,
// 'remarkPlugins'가 적용되지 않았습니다.
})
]
});

Astro는 .md 및 기타 Markdown 파일 유형을 포함하여 /src/pages/ 디렉터리 내 지원되는 모든 파일을 페이지로 취급합니다.

이 디렉터리 또는 하위 디렉터리에 파일을 배치하면 파일 경로명을 사용하여 페이지 경로를 자동으로 빌드하고 HTML로 렌더링된 Markdown 콘텐츠가 표시됩니다.

src/pages/page-1.md
---
title: Hello, World
---
# Hi there!
This Markdown file creates a page at `your-domain.com/page-1/`
It probably isn't styled much, but Markdown does support:
- **bold** and _italics._
- lists
- [links](https://astro.build)
- <p>HTML elements</p>
- and more!

Markdown 페이지의 제한된 기능을 지원하기 위해, Astro는 Astro Markdown 레이아웃 컴포넌트에 대한 상대 경로인 특별한 프런트매터 layout 속성을 제공합니다. Markdown 파일이 src/pages/에 있는 경우 레이아웃 컴포넌트를 생성하고 이 layout 속성에 추가하여 Markdown 콘텐츠 주위에 페이지 셸을 제공하세요.

src/pages/posts/post-1.md
---
layout: ../../layouts/BlogPostLayout.astro
title: Astro in brief
author: Himanshu
description: Find out what makes Astro awesome!
---
This is a post written in Markdown.

이 레이아웃 컴포넌트는 Astro 템플릿의 Astro.props를 통해 특정 속성을 자동으로 사용할 수 있는 일반 Astro 컴포넌트입니다. 예를 들어, Astro.props.frontmatter를 통해 Markdown 파일의 프런트매터 속성에 액세스할 수 있습니다:

src/layouts/BlogPostLayout.astro
---
const {frontmatter} = Astro.props;
---
<html>
<!-- ... -->
<h1>{frontmatter.title}</h1>
<h2>Post author: {frontmatter.author}</h2>
<p>{frontmatter.description}</p>
<slot /> <!-- Markdown content is injected here -->
<!-- ... -->
</html>

또한, 레이아웃 컴포넌트에서 Markdown 스타일을 지정할 수도 있습니다.

Markdown 레이아웃에 대해 더 자세히 알아보세요.

원격 마크다운 가져오기

섹션 제목: 원격 마크다운 가져오기

Astro에는 실험적 콘텐츠 컬렉션 이외의 원격 Markdown에 대한 기본 지원은 포함되어 있지 않습니다!

원격 Markdown을 직접 가져와 HTML로 렌더링하려면 NPM에서 자체 Markdown 파서를 설치 및 구성해야 합니다. 이렇게 하면 사용자가 구성한 Astro의 기본 제공 Markdown 설정이 상속되지 않습니다.

이를 프로젝트에서 구현하기 전에 이러한 제한 사항을 이해하고, 대신 콘텐츠 컬렉션 로더를 사용하여 원격 마크다운을 가져오는 것을 고려하세요.

src/pages/remote-example.astro
---
// 예: 원격 API에서 마크다운 가져오기
// 런타임에 HTML로 렌더링합니다.
// "marked" 사용 (https://github.com/markedjs/marked)
import { marked } from 'marked';
const response = await fetch('https://raw.githubusercontent.com/wiki/adam-p/markdown-here/Markdown-Cheatsheet.md');
const markdown = await response.text();
const content = marked.parse(markdown);
---
<article set:html={content} />
기여하기

여러분의 생각을 들려주세요!

GitHub Issue 생성

우리에게 가장 빨리 문제를 알려줄 수 있어요.

커뮤니티