*로 시작한 줄이 글머리 기호 목록으로 바뀌었다. # 가격 목록이라고 적었더니 페이지 제목이 되었다. <version>이라고 쓴 플레이스홀더가 미리보기에서 사라졌다. 모두 마크다운이 특수문자를 '서식 지시어'로 해석해 발생한 현상이며, 오류 메시지는 전혀 나타나지 않습니다. 이 글에서는 특수기호를 문자 그대로 표시하기 위한 이스케이프 작성법과 함께, 4개 렌더러에서 22개 사례를 실측한 결과를 설명합니다.
먼저 결론 — 기호 바로 앞에 백슬래시() 하나를 둡니다
표시하고 싶은 특수문자 바로 앞에 백슬래시 \를 1개 적습니다. 이것으로 끝입니다.
\*이 문장은 기울임꼴이 되지 않습니다\*
백슬래시 자체는 결과 화면에 나타나지 않습니다. 위 예제는 앞뒤의 별표를 포함해 *이 문장은 기울임꼴이 되지 않습니다*라는 문자열 그대로 표시됩니다.
백슬래시 자체를 화면에 표시하고 싶을 때는 두 개를 겹쳐서 \\로 적습니다.
증상별 빠른 해결표
"어떤 문제가 발생했는가"로부터 원인이 되는 특수문자를 역으로 찾을 수 있도록 정리했습니다. 모두 뒤에서 다룰 실측으로 확인한 증상입니다.
| 발생한 문제 | 원인 | 해결 방법 |
|---|---|---|
| 기울임꼴(이탤릭) 또는 굵은 글씨가 됨 | *나 _로 단어를 감쌈 | 앞에 \*, \_ 붙이기 |
| 줄 전체가 제목(헤딩)이 됨 | 줄 맨 앞의 # + 공백 | \#로 변경 |
| 번호 매기기 목록이 됨 | 줄 맨 앞의 "숫자 + 마침표" | 1986\.처럼 마침표 앞에 \. |
| 글머리 기호 목록이 됨 | 줄 맨 앞의 -나 * | \-, \*로 변경 |
| 텍스트가 화면에서 사라짐 | <와 >로 감싼 단어 | \<와 \>로 변경 |
| 표의 셀이 쪼개지거나 뒷부분이 사라짐 | 셀 내부의 파이프(|) | 파이프 앞에 \ (자세한 내용은 후술) |
이스케이프할 수 있는 특수문자 목록 (32종)
CommonMark 사양의 Backslash escapes새 탭에서 열립니다는 "Any ASCII punctuation character may be backslash-escaped(모든 ASCII 구두점 문자는 백슬래시로 이스케이프할 수 있다)"라고 규정하고 있습니다. 대상은 다음 32개 문자입니다.
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
이 규칙의 이면에는 두 가지 반대 규칙이 있으며, 여기서 많은 실수가 발생합니다.
- 대상은 오직 ASCII 특수문자뿐입니다. 영숫자 앞에 붙은 백슬래시는 일반 문자로 그대로 남습니다. 사양은 "Backslashes before other characters are treated as literal backslashes"라고 명시하고 있으며,
\n이라고 적어도 줄바꿈이 되지 않고 백슬래시와 n이 그대로 출력됩니다. - 한글 특수문자나 전각 기호(※, 「」 등)는 애초에 마크다운 서식이 되지 않으므로 이스케이프가 필요 없습니다. 앞에 백슬래시를 두면 백슬래시 자체가 화면에 노출됩니다.
또 하나 중요한 점은 이스케이프 필요 여부가 문자 자체뿐 아니라 "출현 위치"에 따라 결정된다는 것입니다. #이 제목이 되는 것은 줄 맨 앞에 있고 뒤에 공백이 이어질 때뿐이며, 문장 중간의 #은 그대로 써도 안전합니다. 다음 섹션의 실측에서 이 경계를 구체적으로 확인합니다.
실측 — 이스케이프를 안 하면 무슨 일이 생기는가, 백슬래시는 동작하는가
마크다운 이스케이프를 설명하는 글은 많지만, "이스케이프하지 않았을 때 실제로 어떤 일이 일어나는가", "백슬래시가 모든 구현체에서 실제로 동작하는가"를 검증과 함께 보여주는 자료는 드뭅니다. 그래서 22개 테스트 케이스를 4개 구현체에 통과시켜 직접 확인했습니다. 대상은 GitHub 실제 렌더러(Markdown API 경유), marked 18.0.5, remark-gfm 4.0.1, 확장이 없는 엄격한 CommonMark(remark-parse 단독)입니다. 측정일은 2026-07-15이며 재현 스크립트와 원본 데이터는 저장소 내 scripts/benchmarks/markdown-escape-characters/에 있습니다.
주요 케이스의 결과입니다.
| 입력 (실측 케이스 문자열) | 이스케이프하지 않은 결과 | 이스케이프 적용 후 결과 |
|---|---|---|
Buy the *limited edition* today. | 기울임꼴이 됨 (4개 구현체 일치) | \*limited edition\* 그대로 표시 (4개 일치) |
줄 맨 앞의 # price list | h1 제목이 됨 (4개 구현체 일치) | \# price list 그대로 표시 (4개 일치) |
줄 맨 앞의 1986. What a year. | 1986번부터 시작하는 번호 목록이 됨 (4개 구현체 일치) | 1986\. What a year. 그대로 표시 (4개 일치) |
Replace <version> with 2.0 | <version>이 화면에서 사라짐 (4개 구현체 일치) | \<version\>으로 정상 표시 (4개 일치) |
표 셀 내부의 grep a | b | 파이프로 셀이 쪼개지고 헤더 열 수를 초과한 부분은 삭제됨 (GFM 계열 3개 구현체 일치) | 백슬래시 전치로 1개 셀 안에 유지 (GFM 계열 3개 일치) |
"숫자 + 마침표"의 목록화는 특히 놓치기 쉬운 실수입니다. 1.이든 1986.이든 줄 맨 앞에 있으면 번호 매기기 목록으로 해석되어 뒤따르는 문장에 들여쓰기가 적용됩니다. 연도나 모델 번호로 문장을 시작할 때는 마침표를 \.로 이스케이프하세요.
작성한 마크다운이 렌더러에서 어떻게 해석되는지는 Markdown to HTML 변환기에 붙여넣으면 그 자리에서 바로 확인할 수 있습니다. 변환은 브라우저 안에서 완결되며, 붙여넣은 내용은 어디로도 업로드되지 않습니다.


참고로 이 4개 구현체는 모두 CommonMark 계열이어서 이스케이프의 기본 동작이 깔끔하게 일치했습니다. 구현체별 방언 차이가 어디서 발생하는지는 CommonMark와 GFM의 사양 차이에서 비롯됩니다.
사실 이스케이프가 필요 없는 경우
과도한 이스케이프는 마크다운 소스의 가독성을 떨어뜨릴 뿐 아니라 diff 리뷰에서도 노이즈가 됩니다. 실측을 통해 "이스케이프가 불필요하다"고 확인된 대표적인 사례가 3가지 있습니다.
- 단어 내부의 언더스코어:
max_retry_count_limit같은 snake_case는 4개 구현체 모두에서 그대로 표시되었습니다. 단어 중간의_는 강조(기울임)로 해석되지 않습니다. - 공백 없는 해시태그(
#hashtag): 제목이 되는 것은#뒤에 공백이 있을 때뿐이므로,#hashtag는 4개 구현체 모두에서 일반 문자열로 유지되었습니다. - URL이 이어지지 않는 대괄호:
[TODO] 나중에 수정과 같은 표기는 4개 구현체 모두에서 그대로 표시되었습니다. 단 문서 내 어딘가에[TODO]: https://...형태의 참조 링크 정의가 존재한다면 링크로 바뀌므로, 그 경우에만\[TODO\]로 이스케이프합니다.
주의할 점은 별표(*)가 언더스코어와 대칭으로 동작하지 않는다는 것입니다. foo*bar*baz처럼 단어 내부의 별표는 4개 구현체 모두에서 기울임꼴이 되었습니다. snake_case 감각으로 별표를 방치하면 서식이 깨집니다.
백슬래시가 동작하지 않는 곳
CommonMark 사양은 "Backslash escapes do not work in code blocks, code spans, autolinks, or raw HTML(백슬래시 이스케이프는 코드 블록, 코드 스팬, 자동 링크, raw HTML 내부에서는 동작하지 않는다)"라고 명시하고 있습니다. 실측에서도 코드 스팬과 코드 블록 안에 작성한 \*는 4개 구현체 모두에서 백슬래시까지 함께 출력되었습니다.
이는 실무에서 두 가지 중요한 의미를 갖습니다.
- 코드 블록 내부에서는 아무것도 이스케이프할 필요가 없습니다.
*도#도 그대로 적으면 그대로 표시됩니다. - 코드 안에서 이스케이프를 시도하면 오히려 깨집니다.
`\*`라고 쓰면 독자에게 보이는 것은*가 아니라\*입니다.
또 하나, 줄 끝(행 끝)에는 고유한 함정이 있습니다. 사양상 "A backslash at the end of the line is a hard line break(줄 끝의 백슬래시는 강제 줄바꿈)"이며, 실측에서도 4개 구현체 모두 줄 끝의 \를 <br>로 변환했습니다. 줄 끝의 기호를 이스케이프하려다 백슬래시를 맨 마지막에 두면 기호가 아니라 원치 않는 줄바꿈이 생깁니다.
사라지는 문자 — 꺾쇠괄호 < > 주의
다른 기호는 "의도치 않은 서식이 적용되는" 수준이지만, <와 >는 글자가 통째로 사라지는 방식으로 깨집니다. 플레이스홀더를 <version>처럼 적는 습관이 있다면 자주 겪는 사고입니다.
실측에서 Replace <version> with 2.0이라는 줄의 <version>은 4개 구현체 모두에서 화면에 표시되지 않았습니다. 사라지는 방식은 구현체마다 다릅니다. GitHub은 새니타이저(sanitizer)가 미확인 태그를 제거해 본문에서 빠지고, marked와 remark는 raw HTML 태그로 그대로 출력하므로 브라우저가 정의되지 않은 태그로 삼켜 버립니다. 어떤 경로든 독자에게는 보이지 않습니다.
해결 방법은 두 가지입니다.
Replace \<version\> with 2.0
Replace `<version>` with 2.0
\<version\>은 4개 구현체 모두에서 꺾쇠괄호가 포함된 문자로 정상 표시되었습니다. 명령어 파라미터나 코드의 일부로 보여주고 싶다면 코드 스팬(백틱)으로 감싸는 편이 작성 의도를 전달하기에 더 적합합니다.
문서 전체의 예외 — 표(테이블) 셀 안의 파이프(|)는 특별
여기까지의 규칙은 문서 어디서나 동일하지만, 표의 셀 안에 들어 있는 파이프 기호 |만은 예외입니다. 표는 CommonMark 핵심 사양이 아니라 GFM 확장 사양새 탭에서 열립니다에 해당하며, 셀 안에 가공되지 않은 파이프가 있으면 거기서 열이 분리됩니다. 게다가 GFM 사양은 헤더 행의 열 수를 초과한 셀을 "the excess is ignored(초과분은 무시된다)"라고 규정하고 있어, 실측에서도 grep a | b라고 적은 셀은 파이프 위치에서 쪼개진 뒤 뒷부분의 b가 소리 없이 버려졌습니다(GFM 계열 3개 구현체 일치). 데이터가 조용히 유실된다는 점에서 이 문제는 다른 서식 오류와 질적으로 다릅니다.
셀 내부의 파이프는 백슬래시를 붙여 \|로 이스케이프하거나, HTML 문자 참조 |로 표기합니다. 실측에서는 두 방법 모두 GFM 계열 3개 구현체에서 한 셀 내부의 파이프로 정상 표시되었습니다.
| 명령어 |
| --- |
| grep a \| b |
| grep a | b |
CSV나 스프레드시트 데이터로 마크다운 표를 만들 때는 CSV to Markdown 변환기를 활용하면 셀 안의 파이프를 자동으로 이스케이프한 표를 생성해 줍니다. 일일이 셀을 눈으로 검사할 필요가 없으며, 변환은 브라우저 안에서 완료됩니다.
코드로 보여주고 싶다면 코드 스팬으로 감싸기
백슬래시 대신 코드 스팬(백틱 `으로 감싸기)을 써도 특수문자를 그대로 표시할 수 있습니다. 다만 용도 구분이 명확합니다.
- 문장의 일부로 기호를 보여주고 싶다면 백슬래시:
가격은 \*예고 없이\* 변경될 수 있습니다처럼 적으면 본문의 자연스러운 서식을 유지한 채 기호만 표시됩니다. - 코드, 명령어, 파일 경로, 정규표현식으로 보여주고 싶다면 코드 스팬:
C:\Users\name이나\d+같은 문자열은 고정폭 폰트(monospace)로 표시되는 쪽이 독자에게도 코드라는 의도가 분명하게 전달됩니다.
코드 스팬 내부에서는 이스케이프 처리 자체가 동작하지 않으므로, 정규표현식의 \d+를 그대로 적을 수 있는 것이 큰 장점입니다. 기존 HTML 페이지나 서식 있는 텍스트를 마크다운으로 변환할 때의 이스케이프 처리는 HTML 마크다운 변환 가이드를 참고하세요.
작성하는 플랫폼에 따라 백슬래시가 안 통할 수 있다
여기까지의 실측은 마크다운 렌더러 4개 구현체를 대상으로 한 것이지만, 실제로 글을 쓰는 대상은 Slack이나 Notion 같은 협업 도구인 경우도 많으며, 이들은 렌더러와 별개로 취급해야 합니다. 각 서비스 공식 문서에서 확인된 범위를 정리합니다.
| 작성 대상 플랫폼 | \를 통한 이스케이프 지원 여부 | 확인된 공식 근거 |
|---|---|---|
GitHub (.md / Issue / PR) | 지원 | 본 글의 실측(GitHub Markdown API) 및 GFM 사양새 탭에서 열립니다 |
| GitLab | 지원 | GitLab 공식 문서새 탭에서 열립니다에서 예약된 ASCII 문자 31종 열거 |
| Obsidian | 지원 | Obsidian 공식 도움말새 탭에서 열립니다에서 \*, \_, \#, \`, |, \~ 명시 |
| Slack | 미지원 | Slack 공식 문서새 탭에서 열립니다는 &, <, >의 HTML 엔티티만 규정하고 백슬래시는 언급하지 않음 |
| Notion | 공식 문서에 언급 없음 | Notion 공식 도움말새 탭에서 열립니다은 **, *, `, ~ 단축키를 설명하지만 이스케이프 항목은 없음 |
여기서 알 수 있는 사실은 두 가지입니다.
- GitHub·GitLab·Obsidian은 렌더러 구현과 동일한 동작이 공식 보증됩니다. 앞서 살펴본 실측 표가 그대로 적용됩니다.
- Slack에서는 다른 방법을 써야 합니다. Slack의 이스케이프 규정은
&,<,>에 대한 HTML 엔티티뿐이며,*나_를 백슬래시로 무효화하는 방법은 문서화되어 있지 않습니다. 기호를 확실히 그대로 보여주려면 백틱으로 코드 스팬을 만드는 것이 실무적인 우회 방법입니다.
Notion은 공식 도움말에 이스케이프 관련 기재가 없으므로 이 표에서는 "지원" 또는 "미지원"으로 단정하지 않았습니다. 문서화되지 않은 동작을 단 한 번의 실측으로 단정하면 사양 변경 시 잘못된 정보가 되기 때문입니다. Discord 역시 검토 대상이었으나 공식 문서를 직접 확인할 수 없어 표에서 제외했습니다.
자주 묻는 질문
마크다운에서 어떤 특수문자를 이스케이프할 수 있나요?
ASCII 구두점 문자 32종 전체입니다(CommonMark 사양새 탭에서 열립니다). 영숫자나 한글/전각 기호 앞의 백슬래시는 이스케이프가 되지 않고 백슬래시 자체가 문자로 남습니다.
\n이라고 썼는데 줄바꿈이 되지 않습니다
\n은 프로그래밍 언어의 개행 표기법이며 마크다운의 이스케이프가 아닙니다. 백슬래시 뒤에 영문자가 오면 문자 그대로 출력됩니다(4개 구현체 실측 일치). 마크다운에서 줄바꿈을 하려면 빈 줄을 넣어 새 문단을 시작하거나, 줄 끝에 백슬래시를 두어 강제 줄바꿈을 적용하세요.
snake_case의 언더스코어는 이스케이프가 필요한가요?
필요 없습니다. 단어 내부의 _는 4개 구현체 모두에서 강조(기울임)로 해석되지 않았습니다. 단 별표는 예외여서, foo*bar*baz는 단어 내부에서도 기울임꼴로 변환됩니다.
표의 셀 안에 있는 파이프(|)는 어떻게 이스케이프하나요?
파이프 앞에 백슬래시를 붙여 \|로 작성하거나 HTML 문자 참조 |를 사용합니다. 실측 결과 GFM 계열 3개 구현체 모두에서 두 방법이 유효했습니다. CSV에서 표를 생성한다면 CSV to Markdown 변환기가 자동으로 이스케이프를 적용합니다. 표 작성 방법(정렬 지정·빈 셀·줄바꿈)은 마크다운 표 만들기를 참고하세요.
코드 블록 안에서 백슬래시나 특수기호를 보여주고 싶을 때는 어떻게 하나요?
아무것도 하지 않아도 됩니다. 코드 블록과 코드 스팬 내부에서는 이스케이프 처리 자체가 동작하지 않으므로, *도 \도 그대로 적으면 그대로 표시됩니다. 오히려 \*라고 적으면 백슬래시까지 함께 출력됩니다.
정리
- 특수문자를 그대로 표시하는 기본 원칙은 문자 바로 앞에 백슬래시
\를 1개 붙이는 것입니다. 대상은 ASCII 특수문자 32종이며 영숫자에는 적용되지 않습니다. - snake_case,
#hashtag, URL이 이어지지 않는 대괄호는 이스케이프가 불필요합니다. 과도한 이스케이프는 소스 가독성을 해칩니다. - 코드 블록이나 코드 스팬 내부에서는 이스케이프가 동작하지 않으며, 줄 끝의 백슬래시는 강제 줄바꿈이 됩니다.
<와>는 텍스트가 사라지는 방식으로 깨지고, 표 셀 내부의 파이프는 데이터가 유실되는 방식으로 깨집니다. 이 두 가지는 우선적으로 처리하세요.
작성한 마크다운이 어떻게 렌더링되는지 확인하고 싶다면 Markdown to HTML 변환기에 붙여넣어 그 자리에서 확인할 수 있습니다. 무료이며 회원가입도 필요 없고, 브라우저 외부로 데이터가 전송되지 않습니다.