# 마크다운 문법 제대로 쓰기 — 자주 밟는 함정과 접근성까지

> 마크다운 문법을 처음부터 정리했습니다. 실전에 필요한 기본 아홉 가지와, 줄바꿈이 안 되거나 굵게가 깨지거나 구분선이 제목이 되는 함정 셋, 편집기 추천, 그리고 마크다운이 곧 시맨틱 HTML이자 접근성이 되는 이유까지 담았습니다.

**Published:** 2026-08-15 | **Updated:** 2026-08-15

---


"표로 정리해줘"라고 부탁했더니 AI가 세로줄(`|`)과 붙임표(`-`)가 잔뜩 섞인 텍스트를 내놓은 적 있으신가요? 채팅 화면에서는 말끔한 표였는데, 복사해서 메신저에 붙였더니 기호 범벅이 되는 경험이요.

그 기호들의 정체가 **마크다운**(Markdown)입니다. 요즘은 어디서나 마주칩니다. GitHub의 README, 기술 블로그, 노션 같은 노트 앱, 그리고 AI 챗봇의 답변까지요.

배우는 데는 10분이면 됩니다. 그런데 그 10분 뒤에 꼭 한 번은 당황하게 돼요. 엔터를 쳤는데 줄이 안 바뀌거나, 굵게 표시가 별표째 화면에 보이거나 하면서요. 이 글은 **문법 아홉 가지**와 **그 뒤에 오는 함정 셋**을 함께 다룹니다. 그리고 마지막에는 마크다운을 잘 쓰는 습관이 왜 그대로 접근성이 되는지도요.

## 마크다운이 뭔가요 — 20년 넘게 살아남은 "쓰기 편한 일반 텍스트"

마크다운은 **일반 텍스트에 몇 가지 기호로 서식을 표시하는 문법**입니다. 2004년 존 그루버(John Gruber)가 만들었으니 벌써 20년이 넘었어요. 워드처럼 버튼을 눌러 굵게 만드는 대신, 글자를 별표 두 개로 감싸는 식입니다.

```markdown
**이렇게 쓰면** 굵게 나옵니다.
```

핵심 아이디어는 하나입니다. **서식을 입히기 전에도 읽을 수 있어야 한다.** 위 문장은 변환하지 않고 그냥 봐도 어디를 강조했는지 보이잖아요. HTML로 같은 걸 쓰면 `<strong>이렇게 쓰면</strong>`이 되는데, 태그가 내용을 가리기 시작하죠.

파일 확장자는 `.md`입니다. 메모장이든 VS Code든 어떤 편집기로도 열리고, GitHub에 올리면 자동으로 예쁘게 렌더링됩니다. 그래서 쓰이는 곳이 정말 많아요.

- **GitHub의 README** — 저장소 첫 화면에 보이는 소개문이 전부 마크다운입니다.
- **기술 블로그** — 지금 읽고 계신 이 글도 마크다운으로 쓰여서 HTML로 변환된 겁니다.
- **노션·옵시디언 같은 노트 앱** — 내부 문법이 마크다운이거나 마크다운을 가져오고 내보냅니다.
- **개발 문서** — 요즘 오픈소스 문서 사이트 대부분이 마크다운 기반입니다.

> 표준이 하나로 딱 정해져 있지는 않습니다. 원조 마크다운의 모호한 부분을 정리한 **CommonMark**라는 명세가 있고, GitHub이 표·체크박스 등을 얹은 **GFM**(GitHub Flavored Markdown)이 사실상 가장 널리 쓰입니다. 초보 단계에서는 구분하지 않아도 괜찮아요.

## 마크다운 문법, 이만큼이면 됩니다

전체 문법을 외울 필요는 없습니다. 아래 아홉 가지면 README도 블로그 글도 씁니다. 왼쪽처럼 쓰면 오른쪽처럼 보인다고 읽어주세요.

| 서식 | 이렇게 쓰면 | 이렇게 보입니다 |
|---|---|---|
| 제목 | `# 큰 제목` / `## 중간 제목` | 크기가 다른 제목 (`#` 개수 = 단계) |
| 굵게 | `**중요**` | **중요** |
| 기울임 | `*강조*` | *강조* |
| 목록 | `- 항목` | 글머리표 목록 |
| 번호 목록 | `1. 첫째` | 번호 목록 |
| 링크 | `[표시할 글자](https://주소)` | 클릭 가능한 링크 |
| 이미지 | `![이미지 설명](경로.png)` | 이미지 삽입 |
| 코드 | `` `코드` `` | 회색 배경의 `코드` |
| 구분선 | `---` | 가로줄로 내용을 나눔 |

여러 줄 코드는 백틱(`` ` ``) 세 개로 감쌉니다. 여는 쪽에 언어 이름을 붙이면 색까지 입혀줘요.

````markdown
```javascript
const greeting = "안녕하세요";
console.log(greeting);
```
````

인용은 `>`로 시작하고, 표는 아까 보신 것처럼 `|`로 칸을 나눕니다. 여기까지가 사실상 전부입니다. 10분 배워서 10년 쓰는 문법이라는 말이 괜히 나온 게 아니에요.

{{< img src="images/contents/markdown-basics.png" alt="마크다운 기본 문법 아홉 가지를 작성 예시와 렌더 결과로 나란히 보여주는 표 - 제목, 굵게, 목록, 링크, 이미지, 코드, 구분선만 알면 문서 대부분을 쓸 수 있습니다" >}}

## 마크다운이 이상하게 나올 때 — 자주 밟는 함정 셋

문법은 쉬운데 결과가 생각과 다르게 나오는 순간이 꼭 옵니다. 초보가 거의 반드시 겪는 세 가지를 증상별로 모았어요. 여기 나온 결과는 전부 이 블로그의 변환기로 직접 돌려본 것입니다.

### 줄을 바꿨는데 한 줄로 붙어서 나와요

가장 흔한 첫 번째 당황입니다. 엔터를 쳤는데 화면에서는 앞줄에 딱 붙어버리죠.

```markdown
첫째 줄입니다
둘째 줄입니다
```

이건 고장이 아니라 규칙입니다. 마크다운은 **한 번 엔터를 그냥 공백으로 봅니다.** 원고에서 줄을 정리해 쓰라고 만든 배려인데, 처음엔 배신감이 들죠.

문단을 나누고 싶으면 **빈 줄 하나**를 넣습니다. 문단은 그대로 두고 줄만 바꾸고 싶으면 줄 끝에 **공백 두 칸** 또는 **백슬래시(`\`)** 를 붙이면 `<br>`이 됩니다. 주소나 시 구절처럼 줄이 의미를 갖는 경우에 쓰세요.

### 굵게 표시가 별표째 그대로 보여요

한국어로 쓸 때만 만나는 함정입니다. `**초안(draft)**을`처럼 **괄호 뒤에 조사를 붙이면** 강조가 닫히지 않고 별표가 화면에 그대로 나옵니다.

마크다운 규칙상 닫는 `**` 바로 앞이 문장부호이고 뒤가 글자면 강조를 닫지 않거든요. 영어는 단어 사이에 공백이 있어 안 겪는 문제인데, 조사가 공백 없이 붙는 한국어는 정확히 이 조건에 걸립니다.

가장 쉬운 해결은 괄호를 강조 밖으로 빼는 것입니다 — `**초안**(draft)을`. 이 블로그처럼 변환기가 CJK 확장을 지원하면 백슬래시+공백(`**초안(draft)**\ 을`)으로 경계만 표시하는 방법도 있어요.

### `---`를 넣었더니 가로줄 대신 제목이 됐어요

구분선의 함정입니다. **바로 위에 글자가 있으면 구분선이 되지 않습니다.**

```markdown
오늘은 여기까지 정리했습니다
---
```

이렇게 쓰면 가로줄이 생기는 게 아니라, 윗줄이 통째로 **제목(`<h2>`)으로 승격**됩니다. 마크다운에는 글자 아래 `---`를 그어 제목을 표시하는 옛 방식이 있는데 그게 발동하는 거예요. 실제로 시험해보니 목차에까지 그 문장이 제목으로 올라가더군요.

해결은 **위에 빈 줄 하나**를 넣는 것입니다. 헷갈리기 싫으면 `***`나 `___`를 쓰셔도 돼요. 이 둘은 바로 위에 글자가 있어도 제목이 되지 않고 얌전히 가로줄이 됩니다.

> 참고로 글 맨 위의 `---`로 감싼 부분은 구분선이 아니라 **프론트매터**(front matter)입니다. 제목·날짜·태그 같은 문서 정보를 담는 자리로, 블로그 엔진이나 문서 도구가 읽어갑니다. 같은 기호가 위치에 따라 완전히 다른 뜻이 되는 셈이죠.

## 마크다운 편집기(에디터) 추천 — 뭘로 쓰면 되나

메모장으로도 쓸 수 있다고는 했지만, 쓰다 보면 결과가 어떻게 보이는지 바로 확인하고 싶어집니다. 성격이 다른 다섯 가지를 골라봤어요. 처음이라면 이미 쓰는 도구부터 시작하는 게 제일 낫습니다.

| 도구 | 이런 분께 | 가격 | 한 줄 특징 |
|---|---|---|---|
| **VS Code** | 개발자 | 무료 | 이미 깔려 있음. `Ctrl/Cmd+Shift+V`로 미리보기 |
| **Obsidian** | 메모를 오래 쌓는 분 | 무료 | 내 컴퓨터에 `.md` 파일로 저장, 문서 간 연결 |
| **Typora** | 글쓰기에 집중하고 싶은 분 | $14.99 1회 구매 | 쓰는 순간 서식이 입혀지는 화면 |
| **MarkText** | Typora 느낌을 무료로 | 무료·오픈소스 | 비슷한 사용감, 설치형 |
| **StackEdit·Dillinger** | 설치 없이 잠깐 | 무료 | 브라우저에서 바로 열어 씀 |

개발자라면 **VS Code**로 충분합니다. 별도 설치 없이 `.md` 파일을 열고 `Ctrl+Shift+V`(맥은 `Cmd+Shift+V`)를 누르면 미리보기 창이 옆에 뜨거든요. 이 블로그 글도 그렇게 씁니다.

메모를 오래 쌓을 생각이면 **옵시디언**(Obsidian)을 권합니다. 노션과 달리 파일이 **내 컴퓨터에 그냥 `.md`로** 저장돼서, 서비스가 문을 닫아도 글이 남아요. 이게 마크다운을 쓰는 진짜 이유이기도 합니다. 개인이든 업무용이든 무료이고, 유료 라이선스는 후원 성격입니다.

> **Typora**는 14.99달러 1회 구매(구독 아님)로 기기 3대까지 쓰고, 15일 무료 체험이 있습니다. 무료로 비슷한 사용감을 원하면 **MarkText**가 대안이에요. MarkText는 "개발이 멈췄다"는 오래된 글이 아직 검색에 돌아다니는데, 2026년 6월에 0.19.1 릴리스가 나왔고 7월에도 버그 수정 커밋이 이어졌습니다. 지금은 살아 있는 프로젝트입니다.

## 마크다운과 접근성 — 기호 하나가 곧 시맨틱 HTML입니다

여기까지가 "어떻게 쓰나"였습니다. 이제 "왜 이렇게 쓰는 게 중요한가"를 볼 차례예요. 이 블로그가 접근성을 다루다 보니 이 얘기는 좀 길게 하겠습니다. 그럴 값어치가 있거든요.

마크다운은 변환되면 HTML이 됩니다. 그런데 그냥 HTML이 아니라 **의미가 담긴 HTML**로 바뀝니다.

| 이렇게 쓰면 | 이런 HTML이 됩니다 | 보조기술에게 주는 정보 |
|---|---|---|
| `## 제목` | `<h2>` | "여기서 새 절이 시작한다" |
| `- 항목` | `<ul><li>` | "목록이고, 항목이 몇 개다" |
| `1. 항목` | `<ol><li>` | "순서가 있는 절차다" |
| `> 인용` | `<blockquote>` | "남의 말을 옮긴 부분이다" |
| `\| 표 \|` | `<table><th>` | "표의 제목 칸이다" |
| `![설명](img)` | `<img alt="설명">` | 이미지 대신 읽어줄 문장 |

여기서 **보조기술**은 스크린 리더처럼 장애가 있는 사용자의 이용을 돕는 소프트웨어·기기를 말합니다. 스크린 리더 사용자는 화면을 위에서 아래로 훑지 않아요. `H` 키를 눌러 제목만 건너뛰며 문서 지도를 먼저 그리고, 필요한 곳으로 점프합니다. 그 지도를 만들어주는 게 `##` 기호입니다.

이게 왜 특별하냐면, **손으로 HTML을 짜면 저렇게 안 나오는 경우가 많거든요.** 글자를 크게 하고 싶어서 `<div class="big-text">`를 쓰고, 목록처럼 보이게 하려고 `<div>`에 점 모양 배경을 넣는 식이죠. 눈으로는 똑같지만 스크린 리더에게는 그냥 글자 덩어리입니다. 마크다운은 그렇게 쓰고 싶어도 쓸 수가 없어요. **제약이 곧 안전장치**인 셈입니다.

### 그래도 사람이 챙겨야 하는 세 가지

문법이 구조는 만들어주지만, 내용까지 채워주지는 않습니다. 실제 검사에서 걸리는 건 대부분 여기예요.

**1. 이미지 설명(alt)** — 대괄호 안에 적는 글이 그대로 대체 텍스트가 됩니다.

```markdown
![월별 방문자 추이 그래프](chart.png)      ← 정보를 담았으면 이렇게
![chart.png](chart.png)                   ← 최악. 파일명을 읽어줍니다
![](decoration.png)                       ← 장식용 의도라면… 주의가 필요합니다
```

두 번째가 의외로 흔합니다. 편집기가 자동으로 파일명을 넣어주는데 그대로 두는 거죠. 스크린 리더는 "차트 점 피엔지"라고 읽습니다. KWCAG 2.2에서는 **5.1.1 적절한 대체 텍스트 제공**(WCAG 1.1.1, A등급)에 해당하고, 자동 검사 도구가 확실히 잡아내는 항목이라 인증 심사에서도 바로 걸립니다.

세 번째는 설명이 좀 필요합니다. 순수 장식용 이미지는 **대체 텍스트를 비우는 게 정답**입니다. 읽어봐야 방해만 되거든요. 그런데 여기엔 함정이 하나 숨어 있습니다.

> **`alt=""`와 `alt` 없음은 완전히 다릅니다.** 빈 alt는 "이건 장식이니 건너뛰세요"라는 **명시적 신호**라서 스크린 리더가 조용히 지나갑니다. 반면 alt 속성 자체가 없으면 스크린 리더는 읽을 게 없어서 **파일 경로를 대신 읽습니다**. 침묵과 소음의 차이예요.
>
> 문제는 `![](img.png)`가 항상 `alt=""`로 변환되지는 않는다는 겁니다. 표준대로면 빈 alt가 나와야 하는데, 변환기나 테마가 "값이 비었으니 속성을 빼자"고 판단해버리는 경우가 있어요. 이 글을 쓰면서 이 블로그의 테마를 실제로 확인해봤더니 정확히 그렇게 동작하고 있었습니다. 장식용으로 비워둔 게 되레 접근성 오류가 되는 셈이죠.
>
> 그래서 장식 이미지를 다룰 때는 **결과 HTML을 한 번 확인**하시길 권합니다. 개발자 도구로 그 이미지를 찍어보면 `alt=""`가 있는지 없는지 바로 보입니다. 없다면 마크다운 대신 `<img src="..." alt="">`를 직접 쓰는 게 확실합니다.

**2. 링크 텍스트** — `[여기](url)를 클릭하세요` 대신 `[마크다운 공식 문법 문서](url)`로 씁니다. 스크린 리더에는 페이지의 링크만 모아 듣는 기능이 있는데, "여기, 여기, 더보기, 클릭"만 줄줄이 나오면 아무 정보가 없습니다. KWCAG **6.4.3 적절한 링크 텍스트**(WCAG 2.4.4, A등급)입니다.

**3. 제목 단계** — `#` 다음에 바로 `###`으로 뛰면 문서 지도에 구멍이 생깁니다. 글자 크기를 키우려고 제목 기호를 쓰는 게 대표적인 원인이에요. 크기가 마음에 안 들면 CSS로 조정할 일이지 `#` 개수로 조절할 일이 아닙니다. KWCAG **6.4.2 제목 제공** 관련 항목입니다.

> 참고로 자동 검사 도구인 axe에서 제목 단계 건너뛰기(`heading-order`)와 빈 표 헤더(`empty-table-header`)는 WCAG 위반이 아니라 **"권장"(best-practice)으로 분류**됩니다. 반면 이미지 alt 누락과 링크 텍스트 없음은 명확한 **WCAG A 위반**이에요. 급할 때 어디부터 고칠지 판단하는 기준이 됩니다. 물론 권장 항목도 실제 사용자 경험에는 영향이 큽니다.

### 표를 쓸 때 자주 걸리는 함정

비교표를 만들 때 좌상단 칸을 습관적으로 비우는 분이 많습니다. 이러면 안 됩니다.

```markdown
<!-- 이렇게 쓰면 <th></th> 빈 제목 칸이 생깁니다 -->
|  | 무료 | 유료 |
|---|---|---|
| 가격 | 0원 | 월 1만 원 |

<!-- 좌상단에 행들을 대표하는 라벨을 넣어주세요 -->
| 구분 | 무료 | 유료 |
|---|---|---|
| 가격 | 0원 | 월 1만 원 |
```

마크다운 표는 **첫 행이 통째로 `<th>`(제목 칸)로 변환**되기 때문에, 비워두면 이름 없는 제목 칸이 생깁니다. KWCAG **7.3.2 표의 구성**(WCAG 1.3.1)에서 다루는 영역이에요. 이 블로그도 같은 실수를 했다가 고치고 나서, 아예 작성 규약에 적어뒀습니다.

한 가지는 마크다운의 **한계**로 알아두시면 좋습니다. 마크다운 표는 열 제목만 표현할 수 있고 행 제목(`scope="row"`)은 표현하지 못합니다. 가로·세로 양쪽에 제목이 필요한 복잡한 표라면 마크다운을 포기하고 HTML `<table>`을 직접 쓰는 게 맞아요. 문서 언어를 바꾸는 `lang` 속성도 마크다운만으로는 안 됩니다. 마크다운이 만능은 아니라는 뜻이죠.

## 한 장 요약

- **마크다운**은 일반 텍스트에 기호로 서식을 표시하는 문법. `.md` 확장자, 어디서든 열림.
- 문법은 아홉 가지(제목·굵게·기울임·목록·번호·링크·이미지·코드·구분선)면 실전 충분.
- 함정 셋: **엔터 한 번은 줄바꿈이 아니다** · **조사 앞 굵게가 깨진다** · **`---` 위엔 빈 줄이 필요하다**.
- 편집기는 개발자면 **VS Code**, 메모를 쌓을 거면 **옵시디언**부터.
- 마크다운은 **시맨틱 HTML로 변환**되므로 구조는 공짜 — 대신 **alt 내용·링크 텍스트·제목 단계**는 사람이 챙긴다.
- `alt=""`(장식 신호)와 **alt 없음**(파일 경로를 읽음)은 다르다. 결과 HTML을 확인할 것.
- 표 좌상단 제목 칸을 비우지 말 것. 행 제목이 필요한 복잡한 표는 HTML로.

{{< faq >}}

## 이어서 읽기

문법을 익히셨다면 다음은 요즘 저장소에 하나둘 늘어나는 그 파일들입니다. `CLAUDE.md`, `AGENTS.md`, `DESIGN.md` 같은 것들인데, 전부 여기서 배운 마크다운으로 쓰여 있고 사람이 아니라 **AI가 읽는** 문서예요.

- [AI 시대의 마크다운 — CLAUDE.md·AGENTS.md·DESIGN.md는 각각 뭐 하는 파일인가]({{< relref "/posts/markdown-ai-era" >}})

## 참고 자료

- [CommonMark 명세](https://commonmark.org/)
- [GitHub Flavored Markdown 기본 문법](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
- [마크다운 원본 문서 (John Gruber)](https://daringfireball.net/projects/markdown/)
- [Obsidian](https://obsidian.md/) · [Typora](https://typora.io/) · [MarkText](https://github.com/marktext/marktext) · [StackEdit](https://stackedit.io/)

