Markdown에서 HTML로의 변환은 현대 웹 개발에서 가장 중요한 워크플로우 중 하나입니다. 수백만 명의 개발자가 Markdown 변환기를 사용하여 경량 일반 텍스트를 구조화된 HTML로 변환합니다. 블로그 포스트, README 파일, 문서 사이트 구축까지 이 가이드가 모든 것을 다룹니다. 무료 온라인 도구로 라이브 미리보기와 함께 즉시 변환할 수 있습니다.
라이브 미리보기가 포함된 무료 온라인 Markdown에서 HTML 변환 도구를 사용해 보세요.
TL;DR (요약)
Markdown은 HTML로 변환 가능한 경량 일반 텍스트 서식 언어입니다. JavaScript에서는 markdown-it(확장 가능, CommonMark 호환) 또는 marked(경량 고속)를 추천합니다. Python에서는 mistune(최빠름) 또는 markdown 라이브러리. CLI에서는 pandoc. React 프로젝트에서는 react-markdown 또는 MDX. GFM은 테이블, 작업 목록, 취소선을 추가합니다. 사용자 입력 Markdown은 항상 XSS 정화하세요. @tailwindcss/typography의 prose 클래스로 스타일링.
핵심 요약
- Markdown은 3단계 파이프라인(토큰화, AST 구축, HTML 렌더링)으로 HTML로 변환
- CommonMark이 기본 사양이고, GFM이 테이블, 작업 목록, 취소선 등을 추가
- 주요 라이브러리 비교: marked(빠르고 가벼움), markdown-it(확장 가능), remark(AST 기반), Goldmark(Go 언어)
- 보안 우선: 사용자 생성 Markdown은 항상 DOMPurify로 XSS 정화
- 고급 확장: 수학(KaTeX), Mermaid 다이어그램, 프론트 매터, 목차 생성
Markdown이란?
Markdown은 2004년 John Gruber가 만든 경량 마크업 언어입니다. 읽고 쓰기 쉬운 일반 텍스트 서식 구문으로, 유효한 HTML로 변환할 수 있습니다. HTML의 장황한 꺾쇠 태그와 달리 Markdown은 직관적인 구두점 문자를 사용합니다.
Markdown은 웹 콘텐츠 작성의 사실상 표준이 되었습니다. GitHub의 README 파일, Reddit의 댓글, Stack Overflow의 질문과 답변에서 사용됩니다. Hugo, Jekyll, Gatsby, Astro 같은 정적 사이트 생성기가 Markdown 파일로 HTML 페이지를 생성합니다.
Markdown의 매력은 단순성과 이식성에 있습니다. .md 파일은 일반 텍스트로, 모든 에디터와 OS에서 사용할 수 있습니다.
Markdown 구문 참조
Markdown 구문을 이해하는 것이 효과적인 변환의 첫 번째 단계입니다:
제목: #에서 ######까지 레벨 1부터 6까지 나타냅니다.
굵게와 기울임: 별표 1개로 기울임, 2개로 굵게, 3개로 굵은 기울임체.
링크와 이미지: [텍스트](URL)로 링크, 로 이미지.
코드: 백틱 1개로 인라인 코드, 3개로 코드 블록.
목록: -, *, +로 순서 없는 목록, 숫자로 순서 있는 목록.
인용: 줄 앞에 >를 붙여 인용 블록 생성.
테이블: 파이프(|)와 하이픈(-)으로 테이블 생성.
수평선: 하이픈 3개(---), 별표(***), 밑줄(___).
작업 목록: - [ ]로 미체크, - [x]로 체크.
Markdown에서 HTML로의 변환 원리
Markdown 파서는 3가지 주요 단계의 파이프라인을 통해 일반 텍스트를 HTML로 변환합니다:
1단계 - 토큰화: 파서가 Markdown 문자열을 읽고 토큰 스트림으로 분해합니다.
2단계 - AST 구축: 토큰 스트림이 추상 구문 트리로 조직됩니다.
3단계 - HTML 렌더링: AST를 순회하며 각 노드를 해당 HTML 요소로 변환합니다.
CommonMark 사양은 600개 이상의 예제와 함께 Markdown 구문의 엄격한 정의를 제공합니다.
코드 예제: Markdown에서 HTML로
JavaScript / Node.js (marked, markdown-it, showdown, remark)
JavaScript는 Markdown에서 HTML로의 변환에 가장 풍부한 에코시스템을 제공합니다:
// ===== marked.js (fast, lightweight) =====
import { marked } from 'marked';
const markdown = '# Hello World\n\nThis is **bold** and *italic*.';
const html = marked(markdown);
// <h1>Hello World</h1>
// <p>This is <strong>bold</strong> and <em>italic</em>.</p>
// Configure marked options
marked.setOptions({
gfm: true, // GitHub Flavored Markdown
breaks: true, // Convert \n to <br>
pedantic: false, // Conform to CommonMark
sanitize: false, // Use DOMPurify instead
});
// ===== markdown-it (extensible, plugin-based) =====
import MarkdownIt from 'markdown-it';
import markdownItAnchor from 'markdown-it-anchor';
import markdownItToc from 'markdown-it-toc-done-right';
const md = new MarkdownIt({
html: true, // Allow HTML tags in source
linkify: true, // Auto-convert URLs to links
typographer: true, // Smart quotes, dashes
})
.use(markdownItAnchor) // Add anchors to headings
.use(markdownItToc); // Generate table of contents
const result = md.render('# Hello\n\n${toc}\n\n## Section 1\n\nContent here.');
// ===== showdown (browser + Node.js) =====
import showdown from 'showdown';
const converter = new showdown.Converter({
tables: true,
tasklists: true,
strikethrough: true,
ghCodeBlocks: true,
});
const htmlOutput = converter.makeHtml('## Hello\n\n- [x] Task done');
// ===== unified / remark ecosystem (AST-based) =====
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypePrism from 'rehype-prism-plus';
const file = await unified()
.use(remarkParse) // Parse Markdown to mdast
.use(remarkGfm) // Support GFM (tables, etc.)
.use(remarkRehype) // Transform mdast to hast
.use(rehypePrism) // Syntax highlighting
.use(rehypeStringify) // Serialize hast to HTML
.process('# Hello **World**');
console.log(String(file));
// <h1>Hello <strong>World</strong></h1>Python (markdown, mistune, markdown2)
Python에는 Markdown에서 HTML로 변환하기 위한 우수한 라이브러리가 여러 개 있습니다:
# ===== markdown library (standard, extensible) =====
import markdown
# Basic conversion
md_text = "# Hello World\n\nThis is **bold** text."
html = markdown.markdown(md_text)
# <h1>Hello World</h1>
# <p>This is <strong>bold</strong> text.</p>
# With extensions
html = markdown.markdown(md_text, extensions=[
'tables', # GFM-style tables
'fenced_code', # Fenced code blocks
'codehilite', # Syntax highlighting (requires Pygments)
'toc', # Table of contents
'footnotes', # Footnote support
'attr_list', # Attribute lists for styling
'md_in_html', # Markdown inside HTML blocks
])
# ===== mistune (fastest Python Markdown parser) =====
import mistune
# Basic usage
html = mistune.html(md_text)
# Custom renderer for advanced control
renderer = mistune.create_markdown(
escape=False,
plugins=['table', 'footnotes', 'strikethrough', 'task_lists']
)
html = renderer(md_text)
# ===== markdown2 (simple API, many extras) =====
import markdown2
html = markdown2.markdown(md_text, extras=[
"fenced-code-blocks",
"tables",
"strike",
"task_list",
"code-friendly",
"cuddled-lists",
"header-ids",
"metadata",
])
# Convert a file
with open("README.md", "r") as f:
html = markdown2.markdown(f.read(), extras=["fenced-code-blocks"])
# Python-Markdown extension: convert file to HTML file
import markdown
md = markdown.Markdown(extensions=['meta', 'toc'])
md.convertFile(input='doc.md', output='doc.html')Bash / CLI (pandoc, cmark, grip)
커맨드라인 도구로 터미널에서 직접 Markdown을 HTML로 변환할 수 있습니다:
# ===== pandoc (universal document converter) =====
# Basic Markdown to HTML
pandoc README.md -o output.html
# With standalone HTML (includes <head>, <body>)
pandoc README.md -s -o output.html
# With table of contents and syntax highlighting
pandoc README.md -s --toc --highlight-style=tango -o output.html
# GFM input format
pandoc -f gfm -t html README.md -o output.html
# With custom CSS
pandoc README.md -s --css=style.css -o output.html
# Convert multiple files
pandoc ch1.md ch2.md ch3.md -s --toc -o book.html
# ===== cmark (reference CommonMark implementation) =====
# Basic conversion
cmark README.md > output.html
# With smart typography (quotes, dashes)
cmark --smart README.md > output.html
# GFM extensions (cmark-gfm)
cmark-gfm -e table -e strikethrough -e tasklist README.md
# ===== grip (GitHub-flavored preview) =====
# Preview README in browser (uses GitHub API)
grip README.md
# Export to HTML file
grip README.md --export output.html
# Preview on specific port
grip README.md 0.0.0.0:8080
# ===== Simple pipe conversion with Node.js =====
echo "# Hello **World**" | npx marked
# <h1>Hello <strong>World</strong></h1>
cat README.md | npx marked > output.htmlReact / Next.js (react-markdown, MDX, rehype)
React와 Next.js에서는 컴포넌트 레벨에서 변환이 이루어집니다:
// ===== react-markdown (React component) =====
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
function MarkdownPreview({ content }: { content: string }) {
return (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeHighlight]}
components={{
// Custom component overrides
h1: ({ children }) => (
<h1 className="text-3xl font-bold mb-4">{children}</h1>
),
a: ({ href, children }) => (
<a href={href} className="text-blue-600 hover:underline"
target="_blank" rel="noopener noreferrer">
{children}
</a>
),
code: ({ className, children, ...props }) => {
const isInline = !className;
return isInline
? <code className="bg-gray-100 px-1 rounded">{children}</code>
: <code className={className} {...props}>{children}</code>;
},
}}
>
{content}
</ReactMarkdown>
);
}
// ===== MDX (Markdown + JSX) in Next.js =====
// next.config.js
import createMDX from '@next/mdx';
const withMDX = createMDX({
extension: /\.mdx?$/,
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypeHighlight],
},
});
export default withMDX({
pageExtensions: ['ts', 'tsx', 'md', 'mdx'],
});
// app/blog/[slug]/page.tsx
import { MDXRemote } from 'next-mdx-remote/rsc';
export default async function BlogPost({ params }) {
const source = await getMarkdownContent(params.slug);
return <MDXRemote source={source} />;
}
// ===== Syntax highlighting with Shiki =====
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeShiki from '@shikijs/rehype';
import rehypeStringify from 'rehype-stringify';
const html = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShiki, { theme: 'github-dark' })
.use(rehypeStringify)
.process(markdownContent);GitHub Flavored Markdown (GFM)
GitHub Flavored Markdown (GFM)은 GitHub이 개발한 CommonMark의 상위 집합으로, 소프트웨어 개발에 필수적인 기능을 추가합니다.
테이블: GFM 테이블은 콜론으로 열 정렬을 지원합니다.
작업 목록: GitHub Issue와 PR에서 체크박스로 렌더링됩니다.
취소선: 이중 물결표(~~삭제~~)로 <del> 태그를 사용한 취소선.
자동 링크: GFM은 URL을 자동으로 클릭 가능한 링크로 변환합니다.
각주와 알림: 확장 GFM은 각주와 알림 블록을 지원합니다.
<!-- GFM Examples and their HTML output -->
<!-- Table with alignment -->
| Feature | CommonMark | GFM |
|:--------------|:----------:|------:|
| Tables | No | Yes |
| Task Lists | No | Yes |
| Strikethrough | No | Yes |
| Autolinks | No | Yes |
<!-- Converts to: -->
<table>
<thead>
<tr>
<th style="text-align:left">Feature</th>
<th style="text-align:center">CommonMark</th>
<th style="text-align:right">GFM</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
<!-- Task list -->
- [x] Write the documentation
- [x] Add code examples
- [ ] Publish the article
<!-- Strikethrough -->
~~This text is deleted~~
<!-- Autolink -->
Visit https://example.com for details.
<!-- Footnote -->
Here is a statement[^1] with a footnote.
[^1]: This is the footnote content.
<!-- Alert blocks (GitHub-specific) -->
> [!NOTE]
> This is a note callout.
> [!WARNING]
> This is a warning callout.고급 Markdown 기능
Markdown 에코시스템은 확장과 플러그인을 통해 많은 고급 기능을 지원합니다:
사용자 정의 컨테이너: markdown-it-container와 remark-directive로 사용자 정의 블록 요소를 정의할 수 있습니다.
수학 표기법 (KaTeX / MathJax): 과학 기술 문서에 필수적인 수학 렌더링.
Mermaid 다이어그램: 텍스트 구문에서 다이어그램을 생성합니다.
프론트 매터: YAML 메타데이터로 제목, 날짜, 저자, 태그를 저장합니다.
목차 생성: 플러그인이 제목에서 자동으로 목차를 생성합니다.
<!-- Custom container (markdown-it-container) -->
::: warning
This is a warning message. Be careful!
:::
<!-- Renders as: -->
<div class="warning">
<p>This is a warning message. Be careful!</p>
</div>
<!-- Math with KaTeX -->
Inline math: $E = mc^2$
Display math:
$$
\sum_{i=1}^{n} x_i = \frac{n(n+1)}{2}
$$
<!-- Mermaid diagram -->
```mermaid
graph TD
A[Markdown Source] --> B[Tokenizer]
B --> C[AST Builder]
C --> D[HTML Renderer]
D --> E[HTML Output]
```
<!-- Front matter (YAML) -->
---
title: "My Blog Post"
date: 2024-01-15
author: "John Doe"
tags: [markdown, html, tutorial]
---
# My Blog Post
Content starts here...
<!-- Table of contents (remark-toc) -->
## Table of Contents
<!-- Auto-generated from headings -->
- [Introduction](#introduction)
- [Getting Started](#getting-started)
- [Advanced Usage](#advanced-usage)Markdown 모범 사례
모범 사례를 따르면 일관성 있고 접근 가능한 Markdown 파일을 보장합니다:
일관된 제목 계층: H1부터 시작하여 순서대로 사용하세요.
설명적인 대체 텍스트: 이미지에 항상 의미 있는 대체 텍스트를 제공하세요.
의미론적 줄바꿈: 문장 경계에서 줄바꿈하여 diff를 읽기 쉽게 만드세요.
markdownlint로 린트: markdownlint로 일관된 스타일을 강제하세요.
접근성: 올바른 제목 구조와 설명적인 링크 텍스트를 보장하세요.
역변환은 HTML에서 Markdown으로 변환기, 콘텐츠 길이 확인은 단어 수 세기도 참조하세요.
자주 묻는 질문
Markdown을 HTML로 변환하는 방법은?
JavaScript에서는 marked.js, markdown-it, showdown, Python에서는 markdown이나 mistune, 커맨드라인에서는 pandoc이나 cmark을 사용합니다. 변환 과정은 토큰화, AST 구축, HTML 렌더링으로 구성됩니다.
가장 좋은 Markdown에서 HTML로의 라이브러리는?
JavaScript에서는 markdown-it이 속도와 플러그인 에코시스템으로 가장 인기. React에서는 react-markdown이 표준. Python에서는 mistune이 가장 빠름. pandoc은 만능 커맨드라인 도구입니다.
GFM과 CommonMark의 차이점은?
CommonMark은 원래 Markdown 구문의 엄격한 사양입니다. GFM은 테이블, 작업 목록, 취소선, 자동 링크를 추가한 상위 집합입니다. 대부분의 최신 파서가 둘 다 지원합니다.
React와 Next.js에서 Markdown을 사용할 수 있나요?
네. 가장 인기 있는 접근법은 react-markdown입니다. MDX는 Markdown 안에 JSX 컴포넌트를 삽입할 수 있습니다. Next.js는 @next/mdx와 remark/rehype 플러그인을 지원합니다.
Markdown 코드 블록에 구문 강조를 추가하려면?
Prism.js(rehype-prism), Shiki, highlight.js를 사용합니다. 파서가 언어 식별자를 보존하고, 하이라이팅 라이브러리가 코드를 처리합니다.
Markdown은 XSS 공격으로부터 안전한가요?
원시 Markdown 변환은 XSS에 취약할 수 있습니다. DOMPurify를 사용하거나 파서에서 원시 HTML을 비활성화하세요. 사용자가 생성한 Markdown은 항상 정화하세요.
Markdown에서 생성된 HTML에 스타일을 적용하려면?
Tailwind CSS의 @tailwindcss/typography 플러그인 prose 클래스, github-markdown-css, 또는 react-markdown의 커스텀 렌더러 컴포넌트를 사용합니다.
결론
Markdown에서 HTML로의 변환은 모든 웹 개발자에게 필수적인 기술입니다. 무료 온라인 도구로 즉시 변환하세요.