HTML 이스케이프란 무엇인가요?
HTML 이스케이프는 HTML에서 특별한 의미를 가진 문자를 해당 엔티티 참조로 대체하는 과정입니다. 반드시 이스케이프해야 하는 다섯 가지 문자는 앰퍼샌드(&), 작은따옴표(<), 큰따옴표(>), 큰따옴표("), 작은따옴표(')입니다. 이스케이프하지 않으면 브라우저가 이 문자들을 표시 가능한 텍스트가 아닌 마크업 지시문으로 해석하여 페이지 렌더링이 깨지고 인젝션 공격의 통로가 됩니다.
HTML 명세(WHATWG에서 관리)는 문자 참조의 두 가지 형식을 정의합니다: &처럼 이름이 있는 엔티티와 & 또는 &처럼 숫자 엔티티입니다. 이름 있는 엔티티는 소스 코드에서 읽기가 더 쉽습니다. 숫자 엔티티(10진수 또는 16진수)는 모든 유니코드 코드 포인트를 표현할 수 있어 이름 있는 별칭이 없는 문자에 유용합니다. 두 형식 모두 브라우저에서 동일한 출력을 생성합니다.
언이스케이프(디코딩이라고도 함)는 역방향 연산으로, 엔티티 참조를 리터럴 문자로 다시 변환합니다. 이는 HTML 소스에서 텍스트를 추출하거나, 시스템 간에 콘텐츠를 이동하거나, 엔티티를 이중 인코딩하는 템플릿을 디버깅할 때 흔히 사용됩니다. 이 도구는 브라우저에서 양방향을 모두 처리하므로 이스케이프 로직을 검증하거나 HTML이 많은 소스에서 일반 텍스트를 빠르게 복원할 수 있습니다.
HTML 이스케이프 도구를 사용하는 이유
큰 텍스트 블록에서 꺾쇠 괄호와 앰퍼샌드를 수동으로 교체하는 것은 지루하고 오류가 발생하기 쉽습니다. 전용 도구는 설치 없이 한 번에 입력을 변환합니다.
HTML 이스케이프 활용 사례
HTML 엔티티 참조 표
아래 표는 자주 사용되는 HTML 엔티티를 나열합니다. 다섯 가지 특수 문자(& < > " ')는 HTML 콘텐츠와 속성 값에서 항상 이스케이프해야 합니다. 다른 엔티티는 선택 사항이지만 타이핑하기 어렵거나 소스 코드에서 모호한 문자에 유용합니다.
| 문자 | 설명 | 이름 있는 엔티티 | 숫자 엔티티 |
|---|---|---|---|
| & | Ampersand | & | & |
| < | Less-than sign | < | < |
| > | Greater-than sign | > | > |
| " | Double quote | " | " |
| ' | Single quote / apostrophe | ' | ' |
| Non-breaking space | |   | |
| © | Copyright sign | © | © |
| ® | Registered sign | ® | ® |
| — | Em dash | — | — |
| ’ | Right single quote | ’ | ’ |
| € | Euro sign | € | € |
이스케이프 vs. 언이스케이프: 각각의 사용 시점
두 연산은 역방향 관계입니다. 잘못된 방향을 선택하면 이중 인코딩되거나 보호되지 않은 출력이 생성됩니다.
코드 예시
아래는 4개 언어로 작성된 HTML 이스케이프 및 언이스케이프의 실용적인 예시입니다. 각 스니펫은 양방향을 모두 다루며 중첩된 따옴표와 숫자 엔티티 같은 엣지 케이스를 처리합니다.
// Escape HTML entities manually
function escapeHtml(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
escapeHtml('<img src="x" onerror="alert(1)">')
// → "<img src="x" onerror="alert(1)">"
// Unescape using DOMParser (browser only)
function unescapeHtml(str) {
const doc = new DOMParser().parseFromString(str, 'text/html')
return doc.documentElement.textContent
}
unescapeHtml('<div>Hello</div>')
// → "<div>Hello</div>"import html
# Escape special characters
html.escape('<script>alert("XSS")</script>')
# → '<script>alert("XSS")</script>'
# Escape including single quotes (quote=True is default in Python 3.8+)
html.escape("It's <b>bold</b>", quote=True)
# → 'It's <b>bold</b>'
# Unescape entities back to characters
html.unescape('<p>Price: €10</p>')
# → '<p>Price: €10</p>'
# Unescape numeric entities
html.unescape('<div>&amp;</div>')
# → '<div>&</div>'package main
import (
"fmt"
"html"
)
func main() {
// Escape HTML special characters
escaped := html.EscapeString(`<a href="page?id=1&sort=name">Link</a>`)
fmt.Println(escaped)
// → <a href="page?id=1&sort=name">Link</a>
// Unescape back to original
original := html.UnescapeString("<b>Go & HTML</b>")
fmt.Println(original)
// → <b>Go & HTML</b>
}<?php
// Escape HTML entities (ENT_QUOTES escapes both " and ')
echo htmlspecialchars('<p class="info">Tom & Jerry's</p>', ENT_QUOTES, 'UTF-8');
// → <p class="info">Tom & Jerry's</p>
// Convert all applicable characters to HTML entities
echo htmlentities('Price: 10€ — 50% off', ENT_QUOTES, 'UTF-8');
// → Price: 10€ — 50% off
// Decode entities back
echo html_entity_decode('<div>&copy; 2026</div>');
// → <div>© 2026</div>