HTML 엔티티 인코더 / 디코더

HTML 예약 문자를 엔티티로 바꾸거나 엔티티를 원래 문자로 복원합니다. 비 ASCII 문자를 모두 이스케이프하는 옵션도 제공합니다.

Loading…

모든 처리는 브라우저 내부에서 실행됩니다 — 파일·입력은 서버로 전송되지 않습니다.

사용법

상단의 Encode·Decode를 전환하고 텍스트를 붙여 넣으세요. Encode는 HTML 예약 5 문자(`&`·`<`·`>`·`"`·`'`)를 엔티티 형식(`&amp;`·`&lt;`·`&gt;`·`&quot;`·`&#39;`)으로 치환합니다. "Encode all non-ASCII" 체크박스를 켜면 인쇄 가능 ASCII 외 모든 코드 포인트도 숫자 문자 참조(`&#xxxx;`)로 다시 씁니다. 플레인 ASCII 템플릿 시스템이나 옛 메일 파이프라인에 유용합니다. Decode는 브라우저 자체 HTML 파서를 실행하므로 명명 엔티티(`&copy;`·`&hellip;`), 10진 숫자(`&#169;`), 16진 숫자(`&#xA9;`) 모두 올바르게 처리됩니다.

손으로 HTML을 이스케이프·디코드할 때 사용합니다. 사용자 투고 콘텐츠를 정적 페이지에 끼워 넣을 때, `<`가 여는 태그가 되지 않고 그대로 보이는 원인을 찾을 때, 이미 한 번 이스케이프된 저장 HTML을 확인할 때 같은 상황입니다. React·Vue·Svelte 같은 현대 프레임워크는 보간 값을 자동 이스케이프하므로 애플리케이션 코드 대부분에서는 수동 인코드가 필요 없습니다. 처리는 모두 브라우저 안에서 끝나며 어떤 데이터도 업로드되지 않습니다.

예제

예약 5 문자 인코드

입력
Tom & Jerry <script>alert("xss")</script>
출력
Tom &amp; Jerry &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;

이 5 문자 치환은 신뢰할 수 없는 텍스트를 HTML 본문이나 속성값에 넣기 위한 최소 처리입니다. 인코드 후에는 브라우저가 리터럴 문자로 표시할 뿐 마크업으로 파싱하지 않습니다. script 태그는 텍스트로만 보이고 실행되지 않습니다.

명명·숫자 혼합 엔티티 디코드

입력
&Aacute;rbol &copy; 2024 &mdash; &#x2728; &#x1F600;
출력
Árbol © 2024 — ✨ 😀

명명 엔티티, 10진 숫자(`&#9728;`), 16진 숫자(`&#x2728;`) 모두 한 번의 패스로 디코드됩니다. BMP를 넘는 이모지 코드 포인트는 내부적으로 서러게이트 쌍을 사용하지만 디코드 후에는 단일 글자로 나타납니다.

레거시 템플릿용으로 비-ASCII 전체 인코드

입력
안녕하세요, 世界! €100 💡
출력
&#50504;&#45397;&#54616;&#49464;&#50836;, &#19990;&#30028;! &#8364;100 &#128161;

하류가 7비트 ASCII만 통과시키는 경우(옛 SMTP 릴레이, 일부 로그 전송, 레거시 템플릿 엔진 등)에 비-ASCII 문자 각각을 숫자 엔티티로 바꿉니다. 현대 UTF-8 환경에서는 불필요하며 출력 크기가 커지고 가독성이 떨어집니다.

자주 묻는 질문

아포스트로피에 `&apos;`가 아닌 `&#39;`를 쓰는 이유는?

`&apos;`는 XML과 HTML5에는 있지만 HTML 4에는 없습니다. 옛 브라우저(스크래퍼와 피드 리더에 남아 있는 레거시 파서 포함)는 `&apos;`를 디코드하지 않고 리터럴로 표시하기도 합니다. 숫자형 `&#39;`는 어디서나 동작하므로, 알 수 없는 렌더링 경로를 통과할 가능성이 있는 콘텐츠에는 더 안전한 기본값입니다.

HTML 엔티티 인코딩만으로 XSS를 막을 수 있나요?

HTML 본문 컨텍스트에 한해서입니다. 컨텍스트(HTML 본문·HTML 속성·JavaScript 문자열·CSS 값·URL)마다 전용 인코딩 방식이 필요하며, 값이 `onclick=` 핸들러나 `<style>` 블록에 들어간다면 `<` 이스케이프는 아무 의미가 없습니다. OWASP XSS Prevention Cheat Sheet에는 주요 컨텍스트를 다루는 7가지 규칙이 있습니다. 컨텍스트를 가로지를 가능성이 있는 입력에는 슬롯별로 자동 이스케이프하는 템플릿 시스템(React·Liquid·Mustache 등)을 선택하는 편이 안전합니다.

HTML 엔티티와 URL 퍼센트 인코드 — 어떻게 구분해 쓰나요?

레이어가 달라 역할도 다릅니다. HTML 엔티티(`&amp;`)는 HTML 파서가 마크업으로 해석할 문자를 이스케이프하기 위한 것으로 문서 본문이나 속성값 내부에서 씁니다. 퍼센트 인코드(`%26`)는 URL 구문을 깨뜨릴 문자를 이스케이프하기 위한 것으로 `href`·`src`·폼 전송 쿼리 문자열 내부에서 씁니다. `<a href>` 속성 안에 든 URL의 단일 `&`는 둘이 동시에 필요할 수 있어, `https://x.com/?a=1&amp;b=2`처럼 `&amp;`로 HTML 파서를 만족시키면서 디코드 후에 URL에 리터럴 `&`가 남게 합니다.

한 번도 본 적 없는 이상한 엔티티도 디코드되는 이유는?

디코더는 브라우저 자체 HTML 파서를 사용하므로, HTML5의 명명 엔티티 전 집합(2231개, 그리스 문자·수학 연산자·장식 문자, 심지어 `&Aogon;`(오고넥 붙은 Ą) 같은 별난 문자까지)을 인식합니다. 일반 페이지에서 브라우저가 그릴 수 있는 모든 글자가 이 도구에서도 디코드됩니다. 숫자형(`&#NNN;`과 `&#xHH;`)은 U+10FFFF까지의 전체 코드 포인트를 다룹니다.

`&nbsp;`은 일반 공백과 같은가요?

아니요. `&nbsp;`은 U+00A0(NO-BREAK SPACE)이며, 해당 위치에서의 줄바꿈을 막습니다. 대부분의 폰트에서 일반 공백과 같은 폭으로 보이지만 다른 코드 포인트로 다뤄집니다. 예를 들어 `"a b".split(" ").length`는 2이지만 `"a\u00A0b".split(" ").length`는 1입니다. `&nbsp;`을 YAML 파일·CSV 열·SQL 쿼리에 붙여 넣는 것은 보이지 않는 파싱 에러의 전형적인 원인입니다.

`&lt;script&gt;`을 디코드하면 동작하는 script 태그가 되나요?

텍스트 에디터나 이 도구에서는 디코드하면 리터럴 문자열 `<script>`이 됩니다. 그 문자열을 `innerHTML`로 라이브 페이지에 삽입하면 script 요소는 만들어지지만 실행되지 않습니다. HTML5 명세가 늦은 삽입의 script를 제외하기 때문입니다. DOMParser와 명시적 eval 등가를 결합하면 실행할 수 있지만, 바로 "쉬운 디코드가 쉬운 실행과 같지 않도록" 명세가 그것을 막고 있는 것입니다.

관련 개념

HTML 엔티티는 파서가 렌더링 전에 문자로 치환하는 텍스트 참조입니다. 형식은 3가지입니다. **명명 엔티티**(`&amp;`·`&copy;`·`&hellip;`)는 니모닉 단축이며 HTML5는 2231개를 정의합니다(주요 그리스 문자·수학 연산자·장식 문자 등 포함). **10진 숫자 엔티티**(`&#169;`)는 Unicode 코드 포인트를 10진수로 참조합니다. **16진 숫자 엔티티**(`&#xA9;`)는 같은 것을 16진수로 참조하며 명명 엔티티 집합을 넘는 코드 포인트에 사용합니다. 숫자 형식은 U+10FFFF까지의 모든 코드 포인트를 표현하므로 브라우저가 그릴 수 있는 임의의 문자를 다룰 수 있습니다.

HTML 구문에서는 5 문자가 특별한 의미를 가지며 리터럴 문자로 나타날 때 이스케이프가 필요합니다. `&`(엔티티 시작), `<`(태그 시작), `>`(태그 종료), `"`와 `'`(속성값 구분자)입니다. 앞의 3개는 어떤 HTML 컨텍스트에서나 예약되어 있습니다. 따옴표는 속성값 내부에서만 모호하지만, 이스케이프해 두는 편이 안전한 기본값입니다. 코드 샘플 안의 `<`나 `>`를 이스케이프하지 않고 Markdown 비교 표를 출력하려다 깨지는 이유가 바로 이것입니다.

더 넓은 주제는 **컨텍스트별 출력 인코딩**으로, 구문이 아닌 보안 설계 패턴입니다. 출력 컨텍스트마다 필요한 인코딩이 다릅니다. HTML 본문은 엔티티, HTML 속성은 같은 엔티티에 따옴표를 더한 것, JavaScript 문자열은 백슬래시 이스케이프(`<`는 `\x3C`), URL 컴포넌트는 퍼센트 인코드, CSS 값은 백슬래시 16진(`\3C`)입니다. OWASP의 XSS Prevention Cheat Sheet에 규칙이 정리되어 있습니다. 실용적인 지침은 슬롯별로 자동 이스케이프하는 템플릿 시스템(React JSX·Liquid `{{ }}`·Go `html/template` 등)을 선택해 어떤 인코더를 부를지를 개발자가 판단할 필요가 없게 만드는 것입니다.

관련 도구