본문으로 바로가기
Lab

마크다운 문법, GitHub에서 실제로 어떻게 보이는지 직접 해 보니

마크다운 문법을 GitHub 마크다운 API로 HTML로 바꿔 보면 README 같은 문서와 이슈 댓글에서 엔터 한 번과 체크리스트가 다르게 나옵니다. 제목·강조·목록·표가 무엇이 되는지, Claude Code가 쓴 표도 표가 되는지 명령과 출력으로 보여 드립니다.

·

마크다운 문서 하나가 두 갈래로 나뉘어 한쪽은 줄이 합쳐진 문서 페이지, 다른 쪽은 줄이 나뉘고 체크박스가 생긴 댓글 말풍선이 되는 삽화
마크다운 문법, GitHub에서 실제로 어떻게 보이는지 직접 해 보니 표지 삽화

README에 엔터 한 번으로 줄을 나눴는데 GitHub에서는 한 줄로 붙어 보인 적이 있나요? 같은 마크다운 문법이라도 어디에 쓰느냐에 따라 결과가 달라집니다. 같은 줄바꿈 파일을 GitHub 마크다운 API로 바꿔 보면, 문서 방식에서는 엔터 한 번이 문단 안에 묻히고 댓글 방식에서는 <br>이 붙습니다. 변환 한 번에 걸린 시간은 0.3~0.4초였고, Claude Code에게 표를 쓰게 한 뒤 변환하는 단계는 6.4초였습니다.

마크다운 기본 문법 한눈에 보기

자주 쓰는 문법과 GitHub 마크다운 API(문서 방식)에서 바뀐 결과를 먼저 정리합니다.

이렇게 쓰면이렇게 바뀝니다
# 제목 1큰 제목(<h1>), 앵커 자동 추가
## 제목 2작은 제목(<h2>)
**굵게**굵은 글자(<strong>)
*기울임*기울임 글자(<em>)
`코드`코드 글자(<code>)
- 목록 하나점 목록(<ul>)
1. 순서 하나번호 목록(<ol>)
> 인용문인용(<blockquote>)
[링크](https://solodevnote.com)링크(rel="nofollow" 포함)

표는 세로 막대로 칸을 나누고 둘째 줄에 구분선을 넣습니다.

markdown
| 이름 | 값 |
| --- | --- |
| a | 1 |

README 같은 .md 파일에서는 엔터 한 번으로 줄이 바뀌지 않습니다. 줄 끝에 공백 두 칸을 넣거나 빈 줄을 두어야 하고, 이슈·PR·토론에서는 줄바꿈이 자동으로 렌더링됩니다. 자세한 규칙은 GitHub 기본 쓰기 및 서식 지정 구문 문서에 있습니다. 아래는 이 결과를 직접 재현하는 순서입니다.

함께 읽을 글

따라 할 순서 한눈에 보기

결과부터 말하면 두 방식이 갈린 곳은 엔터 한 번과 체크리스트였습니다. 표와 취소선은 두 방식 모두에서 표와 취소선이 됐습니다. 기본 문법(제목·강조·목록·인용·링크·코드)은 문서 방식에서 예상한 HTML 태그로 바뀌었고요. 아래 순서대로 실행하면 같은 결과를 직접 볼 수 있습니다.

  1. gh --version으로 GitHub CLI가 있는지 확인합니다(측정에서는 이미 로그인된 상태였습니다).
  2. 제목·강조·목록·인용·링크·코드를 담은 basics.md를 만들어 문서 방식으로 바꿉니다.
  3. 엔터 한 번, 줄 끝 공백 두 칸, 빈 줄을 담은 breaks.md를 문서 방식으로 바꿉니다.
  4. 같은 breaks.md를 댓글 방식으로 바꿔 3번 결과와 비교합니다.
  5. 표·체크리스트·취소선을 담은 extra.md를 두 방식으로 각각 바꿉니다.
  6. Claude Code에게 마크다운 표를 쓰게 하고, 그 파일을 문서 방식으로 바꿉니다.

여기서 문서 방식과 댓글 방식은 API의 mode 값을 말합니다. 마크다운 API 문서에 따르면 mode는 markdown과 gfm 중 하나이고 기본값은 markdown입니다. 이 글에서는 markdown을 README 같은 .md 파일에, gfm을 이슈·PR 댓글에 대응시켜 부릅니다.

문서 방식과 댓글 방식을 API 값, 기본값, 이 글에서 대응시킨 쓰임, 저장소 맥락 지정으로 비교한 표
문서 방식은 API 기본값이고, 댓글 방식에서는 저장소를 지정해 이슈 번호를 링크로 바꿀 수 있습니다.
도식출처: 근거를 바탕으로 코드가 그린 도식

기본 문법은 어떤 HTML이 될까요?

먼저 도구를 확인하고, 기본 문법을 모은 파일을 만듭니다.

$ gh --version | head -1
gh version 2.103.0 (2026-10-21)
$ printf '# 제목 1\n## 제목 2\n\n**굵게** *기울임* `코드`\n\n- 목록 하나\n- 목록 둘\n  - 들여 쓴 목록\n\n1. 순서 하나\n2. 순서 둘\n\n> 인용문\n\n[링크](https://solodevnote.com)\n' > basics.md && cat basics.md
# 제목 1
## 제목 2

**굵게** *기울임* `코드`

- 목록 하나
- 목록 둘
  - 들여 쓴 목록

1. 순서 하나
2. 순서 둘

> 인용문

[링크](https://solodevnote.com)

이 파일을 문서 방식으로 바꾸면 GitHub가 만든 HTML이 그대로 돌아옵니다.

$ gh api markdown -f mode=markdown -f text="$(cat basics.md)"
<div class="markdown-heading"><h1 class="heading-element">제목 1</h1><a id="user-content-제목-1" class="anchor" aria-label="Permalink: 제목 1" href="#제목-1"><span aria-hidden="true" class="octicon octicon-link"></span></a></div>
<div class="markdown-heading"><h2 class="heading-element">제목 2</h2><a id="user-content-제목-2" class="anchor" aria-label="Permalink: 제목 2" href="#제목-2"><span aria-hidden="true" class="octicon octicon-link"></span></a></div>
<p><strong>굵게</strong> <em>기울임</em> <code>코드</code></p>
<ul>
<li>목록 하나</li>
<li>목록 둘
<ul>
<li>들여 쓴 목록</li>
</ul>
</li>
</ul>
<ol>
<li>순서 하나</li>
<li>순서 둘</li>
</ol>
<blockquote>
<p>인용문</p>
</blockquote>
<p><a href="https://solodevnote.com" rel="nofollow">링크</a></p>

출력을 문법별로 나누면 이렇습니다.

마크다운GitHub가 만든 HTML
# 제목 1, ## 제목 2<h1>, <h2>와 앵커 링크(#제목-1)
**굵게**<strong>
*기울임*<em>
`코드`<code>
- 목록, 두 칸 들여 쓴 - 목록<ul> 안에 또 하나의 <ul>
1. 순서<ol>
> 인용문<blockquote>
[링크](주소)rel="nofollow"가 붙은 <a>

눈여겨볼 곳은 제목입니다. 제목마다 앵커가 자동으로 붙었고, 제목 1의 공백은 하이픈으로 바뀌어 #제목-1이 됐죠. 기본 쓰기 및 서식 지정 구문 문서도 앵커를 만들 때 글자를 소문자로 바꾸고 공백을 하이픈으로 바꾼다고 설명합니다. AI 에이전트에게 README 목차 링크를 쓰게 한다면, 이 규칙대로 앵커가 만들어졌는지 확인해 보는 게 좋습니다.

엔터 한 번, 문서와 댓글에서 어떻게 다를까요?

그런데 처음에 말한 줄바꿈 문제는 어디서 생길까요? 줄 끝이 눈에 보이도록 ⏎를 찍어서 연습 파일을 만듭니다.

$ printf '첫 줄\n둘째 줄(엔터 한 번)\n\n빈 줄 뒤 셋째 줄\n넷째 줄 끝에 공백 두 칸  \n다섯째 줄\n' > breaks.md && sed 's/$/⏎/' breaks.md
첫 줄⏎
둘째 줄(엔터 한 번)⏎
⏎
빈 줄 뒤 셋째 줄⏎
넷째 줄 끝에 공백 두 칸  ⏎
다섯째 줄⏎

문서 방식으로 바꾼 결과입니다.

$ gh api markdown -f mode=markdown -f text="$(cat breaks.md)"
<p>첫 줄
둘째 줄(엔터 한 번)</p>
<p>빈 줄 뒤 셋째 줄
넷째 줄 끝에 공백 두 칸<br>
다섯째 줄</p>

같은 파일을 댓글 방식으로 바꾸면 이렇게 나옵니다.

$ gh api markdown -f mode=gfm -f text="$(cat breaks.md)"
<p>첫 줄<br>
둘째 줄(엔터 한 번)</p>
<p>빈 줄 뒤 셋째 줄<br>
넷째 줄 끝에 공백 두 칸<br>
다섯째 줄</p>
입력문서 방식댓글 방식
엔터 한 번<br> 없이 같은 문단<br>
줄 끝 공백 두 칸 + 엔터<br><br>
빈 줄새 <p> 문단새 <p> 문단

공식 문서도 같은 내용을 적고 있습니다. 이슈, PR, 토론에서는 줄바꿈이 자동으로 렌더링되지만, .md 파일에서는 줄바꿈 없이 한 줄로 렌더링된다고 하죠. 그래서 .md 파일에서 줄을 바꾸려면 첫 줄 끝에 공백 두 칸을 넣거나, 백슬래시(\)나 <br/> 태그를 붙이라고 안내합니다. 빈 줄은 두 곳 모두에서 문단을 나눕니다.

마크다운 문법이 GitHub에서 보이는 모습 비교 순서를 단계별로 그린 도식
같은 마크다운을 GitHub 마크다운 API의 두 방식(mode=markdown, mode=gfm)으로 바꾼 결과입니다. 열의 README·댓글 표기는 API 모드에 대응시킨 설명입니다. 체크리스트 행은 API 출력 기준이고, 저장소의 README 화면은 확인하지 않았습니다.
도식출처: 직접 실행한 순서

PR 설명에서 멀쩡하던 글을 Claude Code가 README로 옮겨 적으면 줄이 붙어 보일 수 있습니다. 이럴 때는 에이전트에게 "줄을 나눌 곳은 빈 줄로 문단을 나누라"고 규칙을 정해 주는 편이 확실합니다. 줄 끝 공백 두 칸은 파일을 열어 봐도 눈에 띄지 않거든요.

표·체크리스트·취소선은 어떻게 나올까요?

이번에는 표, 체크리스트, 취소선을 한 파일에 담아 문서 방식으로 바꿔 봅니다.

$ printf '| 이름 | 값 |\n| --- | --- |\n| a | 1 |\n\n- [x] 끝난 일\n- [ ] 남은 일\n\n~~취소선~~\n' > extra.md && gh api markdown -f mode=markdown -f text="$(cat extra.md)"
<table>
<thead>
<tr>
<th>이름</th>
<th>값</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>1</td>
</tr>
</tbody>
</table>
<ul>
<li>[x] 끝난 일</li>
<li>[ ] 남은 일</li>
</ul>
<p><del>취소선</del></p>

같은 파일을 댓글 방식으로 바꾼 결과입니다.

$ gh api markdown -f mode=gfm -f text="$(cat extra.md)"
<markdown-accessiblity-table><table role="table">
<thead>
<tr>
<th>이름</th>
<th>값</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>1</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" aria-label="Completed task" checked=""> 끝난 일</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" aria-label="Incomplete task"> 남은 일</li>
</ul>
<p><del>취소선</del></p>
문법문서 방식댓글 방식
표<table>role="table"이 붙은 <table>을 한 겹 더 감쌈
체크리스트[x], [ ]가 글자로 남은 목록체크된 칸과 빈 칸의 체크박스
취소선<del><del>

그렇다면 저장소에 올린 README의 체크리스트도 글자로 남을까요? 이 측정은 API가 돌려준 HTML만 봤기 때문에 github.com 저장소 화면이 어떻게 보이는지는 알 수 없습니다. README에 할 일 목록을 둔다면 저장소에 올려 화면에서 한 번 확인해 보세요. 참고로 공식 문서는 작업 목록 항목 설명이 괄호로 시작하면 \로 이스케이프하라고 안내합니다.

- [ ] \(Optional) Open a followup issue

Claude Code가 쓴 표도 표가 될까요?

AI로 혼자 개발하면 README나 PR 설명의 표를 에이전트가 쓰는 일이 많죠. 그래서 마지막 단계에서는 Claude Code에게 표만 출력하게 하고, 그 결과를 바로 문서 방식으로 바꿨습니다.

$ claude --model opus -p "마크다운 문법 세 가지(제목, 굵게, 코드)를 문법과 쓰는 예 두 열로 정리한 마크다운 표만 출력해. 설명이나 코드 블록 표시는 붙이지 마." > ai-table.md && cat ai-table.md && gh api markdown -f mode=markdown -f text="$(cat ai-table.md)"
| 문법 | 쓰는 예 |
|---|---|
| 제목 | `# 제목` |
| 굵게 | `**굵게**` |
| 코드 | `` `코드` `` |
<table>
<thead>
<tr>
<th>문법</th>
<th>쓰는 예</th>
</tr>
</thead>
<tbody>
<tr>
<td>제목</td>
<td><code># 제목</code></td>
</tr>
<tr>
<td>굵게</td>
<td><code>**굵게**</code></td>
</tr>
<tr>
<td>코드</td>
<td><code>`코드`</code></td>
</tr>
</tbody>
</table>

이 한 번의 실행에서는 요청대로 설명이나 코드 블록 표시 없이 표만 나왔고, GitHub가 그대로 <table>로 바꿨습니다. 백틱 자체를 보여 줘야 하는 칸은 백틱 두 개로 감싸서 <code>`코드`</code>가 됐다는 점도 볼 만합니다. 다만 한 번 실행한 결과이니, 에이전트가 쓴 표를 커밋하기 전에 같은 변환 명령으로 표가 되는지 확인하는 습관을 들이면 안전합니다.

세로 막대로 나뉜 텍스트 줄들이 변환 장치를 지나 머리글 행이 있는 격자 표가 되는 개념 삽화
에이전트가 쓴 파이프 표가 GitHub 변환을 거쳐 표가 되는 흐름을 그린 개념 삽화입니다.

마크다운 사용법, 어디에 쓸지부터 정하기

마크다운 사용법을 찾고 있다면 문법을 외우기 전에 글이 놓일 곳부터 정해 보세요. API의 문서 방식(mode=markdown)과 댓글 방식(mode=gfm)에서 줄바꿈과 체크리스트 결과가 달랐기 때문입니다. 줄바꿈 규칙은 공식 문서도 README 같은 .md 파일과 이슈·PR 댓글에서 다르다고 설명합니다. 반면 체크리스트는 이번 API 비교에서만 차이를 확인했고 README 화면에서는 확인하지 않았으므로, README 화면은 따로 열어 확인해야 합니다. 그다음 문법을 쓰고, 앞에서 쓴 변환 명령에 그곳에 맞는 mode 값을 넣어 미리 확인해 보는 편이 좋습니다. 다만 이 확인은 API 출력을 검사하는 것이고 실제 화면과 같다는 보장은 아니므로, 중요한 문서는 저장소나 댓글 화면에서도 한 번 열어 보는 편이 좋습니다.

API 문서에는 이 측정에서 쓰지 않은 기능도 있습니다.

  • gfm 방식에서 context에 octo-org/octo-repo 같은 저장소를 지정하면 #42가 그 저장소의 42번 이슈 링크로 바뀝니다.
  • 원시 텍스트로 보내는 /markdown/raw 엔드포인트는 GitHub Flavored Markdown을 지원하지 않고 README.md 파일처럼 렌더링하며, 내용은 400 KB 이하여야 합니다.

측정 조건과 한계

  • 환경: 맥 한 대(darwin arm64), Node.js v22.23.1, gh version 2.103.0 (2026-10-21), Claude Code 2.1.309(--model opus)
  • 방법: 새 임시 폴더에서 명령을 차례로 한 번씩 실행했고, 모든 단계의 종료 코드는 0이었습니다. GitHub CLI와 Claude Code는 이미 로그인된 상태였습니다.
  • 측정 시각: 2026-10-26 21:58 KST
  • 한계: API가 돌려준 HTML만 비교했고, 브라우저나 github.com 저장소 화면은 보지 않았습니다. 기본 문법 파일은 문서 방식으로만 바꿨습니다.
  • 한계: 한 번씩만 실행했으므로 걸린 시간은 참고용입니다. Claude Code 단계의 결과도 다시 실행하면 달라질 수 있습니다.
  • 노션·티스토리 같은 다른 서비스의 마크다운 동작은 측정하지 않았으니 이 결과를 그대로 적용하지 마세요.

참고 자료