React에서 innerHTML을 사용하는 방법- dangerouslySetInnerHTML

G_New·2025년 4월 22일

React

목록 보기
3/3

현재 리액트로 진행중인 프로젝트에서, 텍스트 에디터로 작성한 글을 태그 없이 보여줘야 하는 부분이 있다.
처음에는 글을 바로 보여주도록 작성했는데, 태그까지 나와버려서 매우 당황스러웠다 ㅋㅋ

React에서는 기본적으로 HTML 태그를 문자열로 렌더링할 수 없게 막아놨다고 한다.
이걸 어찌 텍스트로 변환해서 보여줘야 할지.. 고민하다가 찾아보니, React에서는 dangerouslySetInnerHTML을 사용한다고 한다!

✨ 공식문서

dangerouslySetInnerHTML

dangerouslySetInnerHTML은 브라우저 DOM에서 innerHTML을 사용하기 위한 React의 대체 방법입니다. 일반적으로 코드에서 HTML을 설정하는 것은 사이트 간 스크립팅 공격에 쉽게 노출될 수 있기 때문에 위험합니다. 따라서 React에서 직접 HTML을 설정할 수는 있지만, 위험하다는 것을 상기시키기 위해 dangerouslySetInnerHTML을 작성하고 __html 키로 객체를 전달해야 합니다.

function createMarkup() {
 return {__html: 'First · Second'};
}

function MyComponent() {
 return <div dangerouslySetInnerHTML={createMarkup()} />;
}

출처 | ⚛️ React 공식문서

말그대로, React에서 innerHTML을 사용하기 위한 방법이지만, 사이트 간 스크립팅 공격, 즉 XSS(Cross-Site Scripting) 공격에 취약하기 때문에 앞에 dangerously를 붙여서 dangerouslySetInnerHTML이라고 작성한다고 한다.

⚠️ XSS(Corss-Site Scripting) 공격

크로스 사이트 스크립팅 또는 교차 사이트 스크립팅(Cross Site Scripting, XSS)은 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나, 피싱 공격을 진행하는 것을 말합니다. XSS 공격은 스크립트 언어와 취약한 코드를 공격 대상으로 합니다.

출처 | ⛰️ 크로스 사이트 스크립팅의 정의 및 공격 유형

누구나 HTML을 변경할 수 있으면, 악의적인 코드를 심어 문제가 발생할 수 있다.
만약 HTML 안에 onmouseover 같은 이벤트 핸들러나 <script> 태그가 들어 있으면, 브라우저가 이걸 실행할 수 있다.

const data = `안녕<b onmouseover="alert('악성코드');">하세요!</b>`

위 data를 dangerouslySetInnerHTML로 넣으면,
사용자가 "하세요!" 위에 마우스를 올렸을 때 alert()가 실행돼서, 악성 코드가 실행될 수 있다.
이게 바로 XSS 공격이다.

👨‍🔧 XSS를 방어하는 법

크게 두 가지 방법이 있다.

1️⃣ DOMPurify

DOM 레벨에서 HTML을 sanitize(소독) 해주고 XSS 공격을 막아준다.

DOMPurify는 HTML을 삭제하고 XSS 공격을 방지한다. 더티 HTML로 가득 찬 문자열을 DOMPurify에 제공할 수 있으며 달리 구성하지 않는 한 깨끗한 HTML이 포함된 문자열을 반환한다.
출처 | https://github.com/cure53/DOMPurify

2️⃣ sanitize-html

허용된 태그와 속성 외에 html 태그를 허용하지 못하도록 한다.

허용할 태그와 속성을 직접 지정할 수 있다.
허용되지 않은 태그는 기본적으로 내용은 남기고 태그만 제거한다.
HTML 주석은 제거되며, 텍스트 내용은 모두 이스케이프 처리된다.
출처 | https://www.npmjs.com/package/sanitize-html?activeTab=readme

나는 이 중 DOMPurify가 패키지 다운로드 수가 높고 최근까지도 활발하게 업데이트 되고 있다고 하여, DOMPurify를 사용하기로 했다.

🦺 DOMPurity 사용하여 위험 요소 걸러내기

🗂️설치 및 import

npm intall dompurify

import DOMPurify from 'dompurify';

🫧 HTML 문자열 sanitize(소독)하기

예를 들어 아래와 같이 사용자 입력이나 API에서 받은 HTML이 있을 때

const dirtyHTML = `안녕<b onmouseover="alert('악성코드');">하세요!</b>`

이걸 DOMPurify로 소독하여 위험한 속성을 제거할 수 있다.

const cleanHTML = DOMPurify.sanitize(dirtyHTML);

이제 cleanHTML은 안녕<b>하세요!</b>만 남게 된다.

⚛️ React 컴포넌트에 안전하게 넣기

이제 이걸 dangerouslySetInnerHTML로 출력하면 된다.

function Card({content}) {
	const sanitizedHTML = DOMPurify.sanitize(html);
    
    return (
    	<div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />
    );
}

<Card content={`안녕<b onmouseover="alert('악성코드');">하세요!</b>`} />

이 과정을 거치면 안전한 상태로 HTML을 텍스트 형태로 불러올 수 있다!

🍎 마무리

React에서 HTML을 텍스트로 불러올 일이 있을 경우 DangerouslySetInnerHTML을 사용해야 하는데, 이 경우 XSS 공격에 취약하므로, 좀 더 안전하게 사용하기 위해서는 DOMPurify를 활용하여 sanitize한 뒤에 사용하는 습관을 들이자!!

profile
기록하는 습관 만들기💫

0개의 댓글