콘텐츠로 이동

Astro에서 Markdown 사용하기

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

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

로컬 Markdown 파일은 src/ 디렉터리 어디에나 저장할 수 있습니다. src/pages/에 위치한 Markdown 파일은 자동으로 사이트에 Markdown 페이지를 생성합니다.

Markdown 콘텐츠와 프런트매터 속성은 로컬 파일 가져오기를 통해, 또는 콘텐츠 컬렉션 헬퍼 함수로 가져온 데이터에서 쿼리하고 렌더링할 때 컴포넌트에서 사용할 수 있습니다.

파일 가져오기 vs 콘텐츠 컬렉션 쿼리

섹션 제목: “파일 가져오기 vs 콘텐츠 컬렉션 쿼리”

로컬 Markdown은 단일 파일의 경우 import 구문을 사용하여, 여러 파일을 한 번에 가져올 때는 Vite의 import.meta.glob()을 사용하여 .astro 컴포넌트로 가져올 수 있습니다. 이렇게 Markdown 파일에서 내보낸 데이터.astro 컴포넌트에서 사용할 수 있습니다.

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

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

파일 가져오기 대신 콘텐츠 컬렉션을 사용하는 경우에 대해 자세히 알아보세요.

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

src/pages/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 compiled = await greatPost.compiledContent();
const posts = Object.values(import.meta.glob("./posts/*.md", { eager: true }));
---
<p>{greatPost.frontmatter.title}</p>
<p>Written by: {greatPost.frontmatter.author}</p>
<Fragment set:html={compiled} />
<p>Post Archive:</p>
<ul>
{
posts.map((post: any) => (
<li>
<a href={post.url}>{post.frontmatter.title}</a>
</li>
))
}
</ul>

헬퍼 함수 getCollection() 또는 getEntry()를 사용하여 컬렉션에서 데이터를 가져올 때, Markdown의 프런트매터 속성은 data 객체(예: post.data.title)에서 사용할 수 있습니다. 또한 body는 원시 형태의 컴파일되지 않은 본문 내용을 문자열로 포함합니다.

render() 함수는 Markdown 본문 내용, 생성된 제목 목록, 그리고 Markdown 프로세서 플러그인이 적용된 후의 수정된 프런트매터 객체를 반환합니다.

컬렉션 쿼리에서 반환된 콘텐츠 사용하기에 대해 자세히 알아보세요.

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

  • file - 절대 파일 경로 (예: /home/user/projects/.../file.md).
  • url - 페이지의 URL (예: /en/guides/markdown-content).
  • frontmatter - 파일의 YAML (또는 TOML) 프런트매터에 지정된 모든 데이터를 포함합니다.
  • <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(product);
---
<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 내보내기 속성으로 제공되는 getHeadings() 유틸리티를 통해, 또는 콘텐츠 컬렉션 쿼리에서 반환된 Markdown을 사용할 때render() 함수를 통해 가져올 수 있습니다.

Markdown 프로세서 플러그인(예: rehype-slug)을 사용해 id 속성을 삽입함으로써 이러한 제목 ID를 사용자 지정할 수 있습니다. 사용자 지정 ID는 Astro의 기본 ID 대신 HTML 출력과 getHeadings()가 반환하는 항목에 반영됩니다.

Astro는 사용자 지정 플러그인이 실행된 후 id 속성을 삽입하므로, 플러그인에서 설정한 모든 ID는 유지됩니다. 사용자 지정 플러그인 중 하나가 Astro가 삽입한 ID에 접근해야 하는 경우, Astro의 제목 ID 플러그인을 가져와 해당 ID에 의존하는 플러그인보다 먼저 배치할 수 있습니다:

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

추가된 버전: astro@6.4.0

Markdown 프로세서는 Markdown 구문을 파싱하고 HTML로 렌더링합니다. 내장 기능을 제공하거나 플러그인을 사용하여 Markdown의 기능을 확장할 수 있습니다.

Astro는 SätteriUnified라는 두 가지 공식 프로세서를 제공합니다. 프로젝트 전체에 프로세서를 구성하거나 Markdown과 MDX 파일에 서로 다른 프로세서를 선택할 수 있습니다.

Astro v7부터 Sätteri가 기본 Markdown 프로세서입니다. 프로젝트의 필요에 따라 별도의 설치나 구성 없이 Markdown 및 MDX 파일을 렌더링하는 데 사용할 수 있습니다.

각 프로세서는 동일한 내장 기능을 제공하지만 아키텍처와 장점에 약간의 차이가 있습니다.

Sätteri는 Astro v7부터 기본 Markdown 프로세서입니다. 다음과 같은 경우에 사용하세요.

  • 빠른 Rust 기반 Markdown 및 MDX 컴파일러의 이점을 활용하려는 경우
  • 프로젝트에 플러그인이 필요하지 않거나 직접 플러그인을 작성할 수 있는 경우

Unified는 이전 Astro 버전에서 사용하던 프로세서입니다. 다음과 같은 경우에 사용하세요.

Astro는 구문 강조와 Markdown 프로세서를 제어할 수 있는 Markdown 구성 옵션을 제공합니다. 또한 각 Markdown 프로세서는 구성 가능한 기능을 제공하며, Markdown 렌더링을 사용자 지정할 플러그인을 추가할 수 있습니다.

Sätteri는 기본적으로 설치나 구성 없이 작동합니다. 기능을 구성하거나 플러그인을 추가하려면 명시적으로 설치하세요.

  1. @astrojs/markdown-satteri 패키지를 설치합니다.

    Terminal window
    npm install @astrojs/markdown-satteri
  2. @astrojs/markdown-satteri에서 satteri를 가져와 Astro 구성의 markdown.processor 옵션에 전달합니다.

    astro.config.mjs
    import { defineConfig } from "astro/config";
    import { satteri } from "@astrojs/markdown-satteri";
    export default defineConfig({
    markdown: {
    processor: satteri(),
    },
    });

두 공식 Markdown 프로세서는 기본적으로 동일한 기능을 제공하며, GitHub-Flavored Markdown스마트 구두점을 지원합니다. 이 기능을 비활성화하거나 사용자 지정할 수 있으며, 플러그인을 추가하여 새로운 기능을 도입할 수도 있습니다.

Astro의 Markdown 프로세서는 기본적으로 GitHub-Flavored Markdown(GFM)을 지원합니다. 이는 원래 Markdown 사양의 상위 집합으로, 표, 취소선, 작업 목록, 각주 등의 기능을 추가합니다.

GFM을 비활성화하려면 프로세서 옵션에서 gfmfalse로 설정하세요.

astro.config.mjs
import { defineConfig } from "astro/config";
import { satteri } from "@astrojs/markdown-satteri";
export default defineConfig({
markdown: {
processor: satteri({ gfm: false }),
},
});

각주를 구성하려면 Sätteri에서는 gfm.footnotes에, Unified에서는 remarkRehype에 구성 객체를 전달하세요.

astro.config.mjs
import { defineConfig } from "astro/config";
import { satteri } from "@astrojs/markdown-satteri";
export default defineConfig({
markdown: {
processor: satteri({
gfm: {
// 기본 각주 구성
footnotes: {
backContent: "",
backLabel: "Back to reference {reference}",
label: "Footnotes",
},
},
}),
},
});
Sätteri에서 각주 구성하기에 대해 자세히 알아보세요.

Astro의 Markdown 프로세서는 기본적으로 Smartypants에 기반한 스마트 구두점을 지원합니다. 이 기능은 곧은 따옴표를 둥근 따옴표로, 하이픈 두 개를 em 대시로, 점 세 개를 줄임표로 자동 변환합니다.

자동 변환을 사용하지 않으려면 프로세서 옵션에서 스마트 구두점을 비활성화할 수 있습니다.

astro.config.mjs
import { defineConfig } from "astro/config";
import { satteri } from "@astrojs/markdown-satteri";
export default defineConfig({
markdown: {
processor: satteri({ smartPunctuation: false }),
},
});

타이포그래피를 더 세밀하게 제어하려면 프로세서 옵션에 구성 객체를 지정할 수도 있습니다.

astro.config.mjs
import { defineConfig } from "astro/config";
import { satteri } from "@astrojs/markdown-satteri";
export default defineConfig({
markdown: {
processor: satteri({
smartPunctuation: {
quotes: true,
dashes: false,
ellipses: false,
},
}),
},
});
Sätteri에서 스마트 구두점 구성하기에 대해 자세히 알아보세요.

Markdown 프로세서 플러그인을 사용하면 목차 자동 생성, 접근 가능한 이모지 레이블 적용, Markdown 스타일 지정처럼 새로운 기능을 추가하여 Markdown을 확장할 수 있습니다. 이러한 플러그인은 처리 파이프라인의 여러 단계에서 구문 트리를 수정할 수 있습니다.

지원되는 플러그인은 두 가지 유형입니다.

  • mdast 플러그인은 HTML로 변환되기 전에 Markdown 구문 트리(mdast)에서 작동합니다. Unified에서는 이를 remark 플러그인이라고 부릅니다.
  • hast 플러그인은 Markdown이 HTML로 변환된 후 HTML 구문 트리(hast)에서 작동합니다. Unified에서는 이를 rehype 플러그인이라고 부릅니다.

mdast 또는 hast 플러그인이 동작을 구성하는 옵션을 허용하는 경우, 플러그인 함수에 옵션 객체로 전달할 수 있습니다.

다음 예시는 Markdown 파일에 satteri-imgattrsatteri-callouts를 적용합니다.

astro.config.mjs
import { defineConfig } from "astro/config";
import { satteri } from "@astrojs/markdown-satteri";
import imgAttr from "satteri-imgattr";
import satteriCallouts from "satteri-callouts";
export default defineConfig({
markdown: {
processor: satteri({
mdastPlugins: [
imgAttr({
defaults: { loading: "lazy", decoding: "async" },
}),
],
hastPlugins: [satteriCallouts()],
}),
},
});

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

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

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

  1. 사용자 지정 속성을 data.astro.frontmatter 객체에 추가합니다.

    data.astro.frontmatter에는 Markdown 또는 MDX 문서의 프런트매터에 있는 모든 속성이 이미 포함되어 있습니다. 따라서 기존 프런트매터 속성을 수정하거나 기존 속성을 바탕으로 새 속성을 계산할 수 있습니다.

    example-mdast-plugin.ts
    import { defineMdastPlugin } from "satteri";
    export const exampleMdastPlugin = defineMdastPlugin({
    name: "example-mdast-plugin",
    text(node, ctx) {
    if (ctx.data.astro !== undefined) {
    ctx.data.astro.frontmatter.newProperty = "새 속성";
    // `title`이 필수 프런트매터 속성이라고 가정
    ctx.data.astro.frontmatter.computedProperty = `${ctx.data.astro.frontmatter.title} | 내 사이트 제목`;
    }
    },
    });
  2. 이 플러그인을 Markdown 구성에 추가합니다.

    astro.config.mjs
    import { defineConfig } from "astro/config";
    import { satteri } from "@astrojs/markdown-satteri";
    import { exampleMdastPlugin } from "./example-mdast-plugin";
    export default defineConfig({
    markdown: {
    processor: satteri({ mdastPlugins: [exampleMdastPlugin()] }),
    },
    });

이제 모든 Markdown 또는 MDX 파일의 프런트매터에 newPropertycomputedProperty가 포함됩니다. 이 속성은 가져온 Markdown 파일, 레이아웃을 사용할 때의 Astro.props.frontmatter 속성, 또는 콘텐츠 컬렉션을 렌더링할 때의 remarkPluginFrontmatter를 통해 사용할 수 있습니다.

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

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는 Markdown 레이아웃 컴포넌트에 대한 상대 경로를 가진 특별한 프런트매터 layout 속성을 제공합니다. layout콘텐츠 컬렉션을 사용하여 Markdown 콘텐츠를 쿼리하고 렌더링할 때는 특별한 속성이 아니며, 의도된 사용 사례를 벗어나면 지원이 보장되지 않습니다.

만약 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>
<head>
<!-- ... -->
<meta charset="utf-8"> // 기본적으로 더 이상 추가되지 않습니다.
</head>
<!-- ... -->
<h1>{frontmatter.title}</h1>
<h2>Post author: {frontmatter.author}</h2>
<p>{frontmatter.description}</p>
<slot /> <!-- Markdown content is injected here -->
<!-- ... -->
</html>

프런트매터 layout 속성을 사용할 때는 Astro가 더 이상 자동으로 추가하지 않으므로 레이아웃에 <meta charset="utf-8"> 태그를 포함해야 합니다. 이제 레이아웃 컴포넌트에서 Markdown을 스타일링할 수도 있습니다.

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

Astro의 내장 Markdown 프로세서는 원격 Markdown 처리에 사용할 수 없습니다.

콘텐츠 컬렉션에서 사용하기 위해 원격 Markdown을 가져오려면, renderMarkdown() 함수에 접근할 수 있는 사용자 정의 로더를 구축할 수 있습니다.

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

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

src/pages/remote-example.astro
---
// 예: 원격 API에서 Markdown 가져오기
// 런타임에 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} />
기여하기 커뮤니티 후원하기