Back

<script>가 실행되지 않는 이유 (HTML Entity와 XSS 방어)

웹 게시판에 글을 쓸 때, <script>alert('해킹');</script>라고 입력하면 어떻게 될까요?

대부분의 안전한 웹사이트에서는 스크립트가 실행되지 않고, 화면에 저 문자열 그대로가 출력됩니다.

브라우저는 < 문자를 보면 "아, 태그가 시작되는구나!"라고 인식하는데, 어떻게 태그로 인식하지 않고 글자로 보여줄 수 있는 걸까요?

그 비밀은 바로 **HTML 엔티티(HTML Entity)**에 있습니다.

1. 예약어의 딜레마

HTML에서 <, >, &, " 같은 문자들은 특별한 의미를 가집니다. 이를 **예약어(Reserved Characters)**라고 합니다.

만약 본문에 "3 < 5"라는 수식을 쓰고 싶어서 그대로 적으면, 브라우저는 < 뒤에 오는 내용을 태그로 해석하려다가 혼란에 빠질 수 있습니다.

따라서 이러한 예약어를 "문자 그대로" 표현하기 위해 약속된 별도의 코드가 필요합니다.

2. 주요 HTML 엔티티

HTML 엔티티는 &로 시작하고 ;로 끝납니다.

  • < (Less Than) -> &lt;
  • > (Greater Than) -> &gt;
  • & (Ampersand) -> &amp;
  • " (Double Quote) -> &quot;
  • ' (Single Quote) -> &#39; (또는 &apos;)
  • 공백 (Space) -> &nbsp; (Non-Breaking Space)

우리가 화면에서 <를 볼 때, 실제 HTML 소스 코드는 &lt;로 되어 있는 것입니다.

3. XSS (Cross Site Scripting) 방어

HTML 엔티티는 보안 측면에서 매우 중요합니다.

해커가 게시판에 악성 스크립트를 삽입하여 다른 사용자의 쿠키를 탈취하거나 악성 동작을 수행하게 만드는 공격을 XSS라고 합니다.

하지만 서버가 사용자의 입력을 저장하거나 출력할 때, <&lt;로, >&gt;로 변환(Escaping)해 버리면 어떻게 될까요?

브라우저는 &lt;script&gt;를 보고 "이건 태그가 아니라 그냥 글자네"라고 판단하여 스크립트를 실행하지 않고 텍스트로 렌더링합니다. 이것이 가장 기본적이고 강력한 XSS 방어 수단입니다.

결론

React나 Vue 같은 현대적인 프론트엔드 프레임워크는 기본적으로 데이터를 출력할 때 자동으로 이스케이핑(Escaping)을 수행합니다.

하지만 dangerouslySetInnerHTML 같은 기능을 사용할 때는 자동 방어가 해제되므로, 반드시 HTML 엔티티 변환 과정을 거쳤는지 확인해야 합니다.

작은 문자 변환 하나가 당신의 웹사이트를 해킹으로부터 지켜주는 방패가 됩니다.

TechHTMLSecurityWeb

관련 도구 둘러보기

Pockit의 무료 개발자 도구를 사용해 보세요