React에서 안전하게 HTML 렌더링하기: dangerouslySetInnerHTML의 대안

2025. 2. 26. 00:39·React
목차
  1. 대안 : html-react-parse + DOMPurify
  2. Custom Hook 구현
  3. DOMPurify의 sanitize 활용하기 / useMemo를 통해 불필요한 리렌더링 막기
  4. 결론

React에서 HTML 문자열을 렌더링해야 하는 경우가 있습니다. 이런 상황에서 dangerouslySetInnerHTML을 사용하게 되는데, 이는 보안과 성능 측면에서 여러 문제를 일으킬 수 있습니다. HTML 아무 제약 없이 그대로 출력된다는 건 XSS 공격의 위험이 있고, 사용자 입력값이 직접 DOM에 주입될 수 있어 위험합니다.

또한 React의 Virtual DOM 을 우회하게 되어, 최적화되지 않고 불필요한 리렌더링을 통해 성능 저하의 원인이 될 수 있습니다

 

대안 : html-react-parse + DOMPurify

 

npm install html-react-parser dompurify @types/dompurify

 

dangerouslySetInnerHTML을 대신하기 위해 위 두 가지 라이브러리를 활용하려고 합니다.

  • html-react-parser: HTML 문자열을 React 요소로 변환
  • DOMPurify: HTML 콘텐츠 필터링 ( 보안성 증가 )

해당 라이브러리를 활용한다면 아래와 같은 형태로 HTML 스트링을 렌더링 할 수 있습니다

import DOMPurify from 'dompurify';
import parse from 'html-react-parser';

// 컴포넌트 내부
<>
  {
	parse(
	  DOMPurify.sanitize(
		HTML String
	  ),
  )}
</>

 

해당 라이브러리를 간단히 활용한다면, 우려했던 XSS 공격을 방지하고 dangerouslySetInnerHTML을 사용하지 않고 HTML String을 렌더링 할 수 있습니다.

저렇게 활용기에, 저희 서비스는 HTML String이 렌더링 되는 경우가 종종 있어서 우선 custom hook을 통해 해당 기능을 재사용 가능하게끔 해보았습니다.

 

Custom Hook 구현

import DOMPurify from 'dompurify';
import parse from 'html-react-parser';

export function useHTMLParse(content: string) {
  return parse(
    DOMPurify.sanitize(content)
  );
}

 

DOMPurify의 sanitize 활용하기 / useMemo를 통해 불필요한 리렌더링 막기

DOMPurify의 sanitize를 활용하면 보다 엄격하게 HTML String을 검사하고 필터링 하여 HTML tag와 속성에 대해 사용하는 것만 HTML로 렌더링 되게끔 할 수 있습니다. 엄격한 검사는 HTML String을 렌더링 하는 과정에서 보안을 더욱 향상해 줄 수 있습니다.

또한 useMemo를 통해 들어오는 HTML String이 변경될때만 HTML 파싱 작업이 실행되도록 하여, 렌더링 성능을 향상할 수 있습니다.

import DOMPurify from 'dompurify';
import parse from 'html-react-parser';

import { useMemo } from 'react';


export function useHTMLParse(content: string) {
  return useMemo(
	() =>
	  parse(
		DOMPurify.sanitize(content, {
		  ALLOWED_TAGS: ['strong', 'br', 'div'],
			ALLOWED_ATTR: [
			  'target',
			  'align'
		  	],
		  }
        ),
    ),
	[content],
  );
}

 

사용 예시

 

function ContentDisplay({ content }) {
  const parsedContent = useHTMLParse(content);
  
  return (
    <div className="content-container">
      {parsedContent}
    </div>
  );
}

 

결론

dangerouslySetInnerHTML 대신 HTML String을 렌더링 하는 custom hook 을 구현해 봤습니다. html-react-parser와 DOMPurify를 조합한다면 보안적으로도 훨씬 안정적인 방법으로 구현할 수 있고, 성능 또한 보다 향상할 수 있는 방법이라고 생각합니다.

저작자표시 변경금지 (새창열림)

'React' 카테고리의 다른 글

[React/Typescript] JSX 요소 형식에 구문 또는 호출 시그니처가 없습니다.  (0) 2025.04.17
Cloudflare에서 성능저하가 심하게 발생한다! ( AWS EC2 + ACM + CloudFront + Route53 + WAF 로 전환하기 )  (0) 2025.03.29
[React] 비즈니스 / 도메인 로직을 통해 코드 응집도 높이기  (3) 2024.12.03
[React] 뒤로가기 시 상태 유지하기 ( useNavigationType, popstate )  (1) 2024.11.15
[React] 웹뷰로 연결된 Android Stuiod / IOS 에 데이터 주고받기 ( 브릿지 통신 )  (0) 2024.11.11
  1. 대안 : html-react-parse + DOMPurify
  2. Custom Hook 구현
  3. DOMPurify의 sanitize 활용하기 / useMemo를 통해 불필요한 리렌더링 막기
  4. 결론
'React' 카테고리의 다른 글
  • [React/Typescript] JSX 요소 형식에 구문 또는 호출 시그니처가 없습니다.
  • Cloudflare에서 성능저하가 심하게 발생한다! ( AWS EC2 + ACM + CloudFront + Route53 + WAF 로 전환하기 )
  • [React] 비즈니스 / 도메인 로직을 통해 코드 응집도 높이기
  • [React] 뒤로가기 시 상태 유지하기 ( useNavigationType, popstate )
설탕시럽
설탕시럽
설탕시럽의 Web Tech Blog 입니다.
SugarSyrup Tech Blog설탕시럽의 Web Tech Blog 입니다.
  • 설탕시럽
    SugarSyrup Tech Blog
    설탕시럽
  • 전체
    오늘
    어제
    • 분류 전체보기 (50)
      • HTML & CSS (2)
      • JavaScript (6)
      • React (17)
      • Node (1)
      • BackEnd (1)
      • 회고 (5)
        • 엄브렐라 개발일지 (1)
        • 인턴 회고!!! (2)
      • 컴퓨터 기초 (4)
        • 운영체제 (2)
        • SICP (1)
      • 코딩테스트 (10)
      • 짧은 글 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    top-level await
    프론트엔드
    React
    nginx
    프로그래머스
    TypeScript
    운영체제
    JavaScript
    회고
    티스토리챌린지
    Element
    인턴
    docker
    리액트
    자바스크립트
    EC2
    JS
    오블완
    php
    에러
    document
    배포
    타입스크립트
    css
    SQL
    error
    level1
    코딩테스트
    CodingTest
    AWS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
설탕시럽
React에서 안전하게 HTML 렌더링하기: dangerouslySetInnerHTML의 대안
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.