마크다운 코드 블록: 구문, 언어 및 예제를 포함한 완벽 가이드
펜스 코드, 언어 태그, diff, 파일명
Fenced 코드 블록은 Markdown에서 여러 줄의 소스를 담는 데 사용됩니다. 시작 펜스 바로 뒤의 토큰은 언어 태그이며, 이 태그가 어떤 하이라이팅을 적용할지 결정하는 것은 렌더러에만 맡겨져 있습니다.
이 가이드는 2026 문서 도구: Markdown, LaTeX, PDF 및 인쇄 워크플로의 일부입니다.

GitHub는 Linguist와 languages.yml 파일의 키워드를 통해 언어 태그를 조회합니다. Hugo 0.164는 같은 태그를 Chroma에 전달합니다. Chroma가 모르는 태그가 있는 경우에도 여전히 코드 블록으로 처리되며, 일반 텍스트로 표시됩니다. 헤딩, 테이블, 기타 블록 유형은 Markdown 치트시트에 정리되어 있습니다.
Markdown 코드 블록 개요
Markdown에서는 코드를 표시하는 세 가지 방법이 있습니다. 인라인 코드는 문단 안의 스팬(span)입니다. 들여쓰기 블록과 펜스(fence) 블록은 모두 여러 줄을 다루지만, 언어 태그를 가질 수 있는 것은 펜스뿐입니다.
| 유형 | 문법 | 하이라이팅 | 비고 |
|---|---|---|---|
| 인라인 코드 | `코드` |
없음 | 문장 내 하나의 스팬 |
| 들여쓰기 블록 | 각 줄마다 4칸 공백 또는 1개 탭 | 없음 | 정보 문자열이 없어 언어 태그 없음 |
| 펜스 블록 | ```lang … ``` 또는 ~~~ |
렌더러가 lang을 알 때 적용 |
GitHub가 문서화하는 형식 |
들여쓰기 블록은 언어를 포함할 수 없습니다. CommonMark는 4칸 들여 쓴 줄을 코드로 취급하지만, 하이라이터가 매칭할 수 있는 정보를 제공하지 않습니다. 이것이 샘플에 색상 적용이 필요한 경우 펜스 형식을 사용해야 하는 이유입니다.
펜스는 최소 3개의 백틱(반점) 또는 3개의 틸드(~)로 구성된 줄, 코드, 그리고 같은 문자 중 최소 같은 길이의 닫는 줄로 이루어집니다. 닫는 줄에는 정보 문자열이 없습니다. 샘플 내에 3백틱 펜스를 표시하려면 4개의 백틱으로 열고 닫습니다. GitHub의 코드 블록 문서에서는 원본 파일의 가독성을 위해 펜스 앞뒤에 빈 줄을 두라고 권장하지만, 빈 줄이 없어도 펜스는 여전히 파싱됩니다.
다음 소스가 Markdown으로 저장된 경우:
```python
def hello():
print("Hello, world!")
```
이 Hugo 사이트에서 다음과 같이 렌더링됩니다:
def hello():
print("Hello, world!")
인라인 코드는 같은 백틱 규칙이 더 작은 규모로 적용됩니다. git status와 같은 짧은 코드는 단일 백틱 한 쌍이면 충분합니다. 스팬 자체에 백틱이 포함되는 경우, 양쪽 모두에 두 개의 백틱을 사용해야 합니다:
`` `code` ``
Diff 문법 하이라이팅
diff로 태그된 펜스는 텍스트 형식으로 변경 사항을 보여주는 방법입니다. Hugo의 Chroma 렉서(lexer)는 diff와 udiff를 지원합니다. GitHub도 언어 목록에서 동일한 식별자를 기반으로 하이라이팅을 수행합니다.
- old line that will be removed
+ new line that will be added
unchanged line
-로 시작하는 줄은 삭제 스타일이, +로 시작하는 줄은 삽입 스타일이 적용됩니다. 접두사가 없는 줄은 해당 렉서에서 일반 텍스트로 처리됩니다. 색상 적용은 줄 전체에 이루어집니다. 줄 중간에서 변경된 단어는 단독으로 표시되지 않습니다.
언어 식별자
정보 문자열의 첫 번째 단어는 언어를 나타냅니다. Hugo의 문서에서 이 단어는 대소문자를 구분하지 않는다고 설명합니다. Chroma에 해당 렉서가 없다면, Hugo 0.164는 하이라이트 래퍼 없이 일반 <pre><code class="language-…"> 요소를 출력합니다. notalang을 로컬에서 렌더링했을 때 이러한 결과가 나타났습니다. guessSyntax 기본값은 false이며, Hugo 문서에 따르면 자동 감지를 구현한 렉서는 5개뿐이므로, 태그가 생략되면 추정된 언어가 아닌 일반 텍스트로 남습니다.
이 펜스들에서 생성되는 HTML은 language-python 클래스와 동일한 토큰을 사용합니다. 이 클래스는 하이라이트된 페이지를 다시 Markdown으로 변환할 때 변환기가 보존해야 하는 요소로, 이는 Python을 사용한 HTML to Markdown 변환에서 다루는 매핑에 해당합니다.
아래 식별자는 Hugo의 Chroma 테이블에 해당 언어별로 나열된 것들입니다. Hugo 0.164 렌더링에서는 cs, yml, markdown도 색상으로 표시되었으며, 게시된 테이블에 csharp, yaml, md로 인쇄되어 있는 경우에도 마찬가지였습니다.
| 언어 | Hugo Chroma 식별자 |
|---|---|
| Python | python, py |
| JavaScript | javascript, js |
| TypeScript | typescript, ts, tsx |
| Java | java |
| C | c |
| C++ | cpp, c++ |
| C# | csharp, c# |
| Go | go, golang |
| Ruby | ruby, rb |
| PHP | php |
| Rust | rust, rs |
| Swift | swift |
| Kotlin | kotlin |
| HTML | html |
| CSS | css |
| Shell | bash, sh, shell, zsh |
| SQL | sql |
| JSON | json |
| YAML | yaml |
| Markdown | md, mkd |
| Perl | perl |
| Lua | lua |
| R | r |
| Matlab | matlab |
| Makefile | make, makefile |
| Diff | diff, udiff |
Jekyll을 통해 여전히 하이라이팅을 수행하는 GitHub Pages 사이트는 식별자가 소문자여야 합니다. GitHub 공식 문서도 github.com 렌더링과 별도로 이 요구 사항을 명시하고 있습니다.
GitHub는 몇몇 펜스를 색상 소스보다는 다이어그램으로 취급하기도 합니다: mermaid, geojson, topojson, stl. Hugo의 Chroma 테이블에는 mermaid가 목록에 없습니다. Hugo 사이트에서는 렌더 훅, 쇼트코드, 또는 스크립트가 이를 그리기 전까지 펜스는 소스 텍스트로 남습니다. Mermaid 다이어그램 퀵스타트와 치트시트에서 해당 설정을 다룹니다.
파일명 지정
CommonMark나 GitHub의 코드 블록 문서 어디에도 정보 문자열을 파일명으로 변환하는 기능이 없습니다. Hugo의 하이라이팅 옵션은 {linenos=inline}와 같은 중괄호 쌍을 사용합니다. 여기에 파일명 필드는 포함되지 않습니다.
언어 뒤의 콜론
몇 가지 생성기는 js:app.js를 언어와 이름의 조합으로 취급합니다:
```js:app.js
console.log("Hello, world!");
```
GitHub는 그렇게 하지 않습니다. Hugo 0.164는 전체 토큰을 코드 요소의 클래스(language-js:app.js)로 유지하며 파일명을 인쇄하지 않습니다. 첫 번째 단어 이후에 의미를 부여하는 변형이 있는지 여부는 GFM vs CommonMark vs Pandoc Markdown에서 비교하고 있습니다.
펜스 위 이름
펜스 위에 볼드 인라인 코드로 작성된 이름 줄은 GitHub, 이 사이트, 그리고 기타 CommonMark 렌더러에서 이름을 표시합니다:
**`app.js`**
```js
console.log("Hello, world!");
```
헤딩도 동일한 방식으로 작동합니다:
#### `app.js`
```js
console.log("Hello, world!");
```
샘플 내 이름
첫 줄의 주석은 블록을 복사할 때 코드와 함께 이동합니다:
```js
// app.js
console.log("Hello, world!");
```
| 방법 | GitHub | Hugo 0.164 | 복사 시 이름 표시 |
|---|---|---|---|
정보 문자열에 js:app.js |
파일명 없음 | 파일명 없음. 클래스는 전체 토큰 | 아니오 |
| 펜스 위 볼드 코드 또는 헤딩 | 있음 | 있음 | 아니오 |
| 첫 줄 주석 | 있음 | 있음 | 있음 |
백틱 이스케이프
바깥쪽에 4개의 백틱을 사용하면 3백틱 펜스가 표시되며, 이는 Markdown을 문서화하는 페이지의 패턴입니다:
````markdown
```python
# This triple-backtick fence is inside a four-backtick fence
print("hello")
```
````
닫는 펜스는 여는 펜스와 같은 문자여야 하며, 길이가 같거나 길어야 합니다. 더 짧은 닫는 펜스는 블록을 조기에 종료시키고 나머지 샘플을 일반 단락으로 남깁니다.
Hugo 하이라이트 옵션
이 사이트의 config.toml에는 [markup.highlight] 블록이 없으므로 Hugo 기본값이 적용됩니다: 펜스 블록은 하이라이트되고, 스타일은 monokai이며, 스타일은 인라인으로 작성됩니다(noClasses가 true), 줄 번호는 꺼져 있습니다. Hugo 0.164에서는 언어만 요청하는 펜스도 색상 처리됩니다. 위의 Python 샘플이 이를 보여줍니다.
줄 번호와 강조 줄은 언어 뒤에 오는 중괄호 옵션입니다. 이 펜스는 인라인 번호를 요청하고 2번째 줄을 강조합니다:
```python {linenos=inline hl_lines=[2]}
def hello():
print("Hello, world!")
```
1def hello():
2 print("Hello, world!")
linenos는 inline, table, true, false를 허용합니다. hl_lines는 줄 번호 또는 범위의 목록입니다. linenostart는 표시되는 첫 번째 번호를 설정합니다. 동일한 키들은 대소문자를 구분하지 않습니다. highlight 쇼트코드는 이들을 하나의 인용 문자열로 받으며, 이 문자열은 Hugo 0.164에서도 여전히 줄 번호를 렌더링했습니다:
{{< highlight python "linenos=true,hl_lines=2" >}}
def hello():
print("Hello, world!")
{{< /highlight >}}
색상을 스타일시트로 옮기려면 `noClasses`를 false로 설정하고 CSS를 생성하세요. Hugo 0.164에서는 해당 명령에 `--mode`와 `--modeSelector`를 지원합니다:
```bash
hugo gen chromastyles --style=monokai --mode=light > assets/css/highlight.css
hugo gen chromastyles --style=monokai --mode=dark --modeSelector > assets/css/highlight-dark.css
--modeSelector는 각 규칙을 .dark .chroma와 같은 최상위 클래스 아래로 범위를 제한합니다. 플래그 목록은 hugo gen chromastyles --help에서 확인할 수 있습니다.
펜스가 잘못 보일 때
샘플을 변경하기 전에 생성된 요소를 먼저 확인하세요. 이 Hugo 버전에서 알려진 언어는 data-lang가 식별자로 설정된 div.highlight입니다. 알려지지 않은 식별자는 notalang이 생성했던 것처럼 class="language-…"가 있는 pre와 code 요소를 그대로 출력합니다.
app.js 이름이 없으면 클래스가 language-js:app.js라면, 콜론 형식이 사용된 것입니다. 이름을 펜스 위 줄로 옮기세요.
튜토리얼 자체의 펜스가 느슨한 단락으로 보인다면, 외부 펜스가 내부 펜스와 길이가 같은 것입니다. 외부 펜스의 길이를 늘리세요.
짧은 명령어가 문장 중간에서 백틱을 삼키면, 스팬은 포함하는 문자보다 긴 백틱 쌍을 필요합니다.