1️⃣ React Quill 사용하기
React Quill은 리액트의 텍스트 에디터 라이브러리 중 하나이다.
위지위그(WYSIWYG, What you see is what you get)라고도 하는데, "보는 대로 얻는다"라는 뜻이다.
즉, 사용자가 텍스트 에디터에서 작성하며 보여지는 그대로 출력물에서 나타나도록 한다.
📍 패키지 설치
yarn add react-quill
📍 기본 코드
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
interface TextEditorProps {
value: string;
onChange: (value: string) => void;
}
const TextEditor = ({value, onChange}: TextEditorProps) => {
const modules = {
toolbar: [
[{list: 'ordered'}, {list: 'bullet'}],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[{color: []}, {background: []}],
[{align: []}],
],
};
return (
<div>
<ReactQuill
value={value}
onChange={onChange}
modules={modules}
className="h-72"
/>
</div>
);
};
export default TextEditor;
- TextEditor 컴포넌트로 만들어 여러 페이지에서 사용했다.
- modules를 활용해 커스텀할 수 있다.
요런 식으로 텍스트 에디터를 넣을 수 있다~!
작성한 내용은 html 형식으로 받을 수 있다.
이를 문자열 형태로 백엔드에 보내 저장한 후, 나중에 다시 백엔드에서 받아 불러올 때는 어떻게 해야 할까?
2️⃣ HTML 렌더링하기
dangerouslySetInnerHTML
이 친구를 활용하면 html 문자열 내용을 렌더링할 수 있다.
const content = '<b>테스트</b>';
return (
<div
className="p-6 bg-white"
dangerouslySetInnerHTML={{__html: content}}
/>
);
다만 문제는.. 보안상의 위험이다!
🚨 XSS 공격
- Cross Site Scripting
- 사용자 입력을 처리할 때 악성 스크립트가 삽입되어 실행되는 취약점이다.
- 사용자의 세션 쿠키를 탈취하거나 악성 코드를 실행하여 사용자의 데이터를 훔치거나 조작할 수 있다.
- 때문에 html을 직접 삽입할 때는 신뢰할 수 있는 데이터만을 사용해야 한다.
하지만 나는 React Quill이라는 텍스트 에디터를 사용해야 하는데, React Quill은 사용자 입력을 html로 반환한다.
그후 클라이언트도 사용자가 입력한 html 내용을 백엔드에게 전달했다가 다시 받아서 사용자에게 띄어줘야 한다.
🦺 안전..?
1. xss 라이브러리
yarn add xss
import xss from 'xss';
interface PostContentProps {
content: string;
}
const PostContent = ({content}: PostContentProps) => {
const safeContent = xss(content);
return (
<div
className="p-6 bg-white"
dangerouslySetInnerHTML={{__html: safeContent}}
/>
);
};
export default PostContent;
2. DOMPurify
- 클라이언트 측에서 HTML을 안전하게 정화(sanitize)하여 악성 스크립트를 제거한다.
- HTML, SVG, MathML 등의 콘텐츠에서 위험한 요소(스크립트, 이벤트 핸들러 등)를 제거하여 안전하게 만든다.
- 허용할 태그나 속성을 지정하는 등의 커스텀이 가능하다.
yarn add dompurify
import DOMPurify from 'dompurify';
interface PostContentProps {
content: string;
}
const PostContent = ({ content }: PostContentProps) => {
const safeContent = DOMPurify.sanitize(content);
return (
<div
className="p-6 bg-white"
dangerouslySetInnerHTML={{ __html: safeContent }}
/>
);
};
export default PostContent;
- DOMPurify 커스텀
const domPurifyConfig: Config = {
ALLOWED_TAGS: [
'b',
'i',
'em',
'strong',
'a',
'p',
'ul',
'li',
'ol',
'br',
'img',
'h1',
'h2',
'h3',
'blockquote',
],
ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'target'],
ALLOW_DATA_ATTR: false, // data-* 속성 허용 여부
RETURN_TRUSTED_TYPE: false, // TrustedType으로 반환 (브라우저 지원 시)
FORCE_BODY: true, // 정화된 결과가 항상 <body>로 래핑되도록 강제
};
🥁 나의 결론
DOMPurify 라이브러리가 xss 라이브러리보다 강력한 것 같아 DOMpurify를 채택했다.
특히 DOMPurify는 커스텀이 되니까 React Quill에서 사용하는 태그만 설정해주면 좋을 것 같다.
반응형
'Library & Runtime > React' 카테고리의 다른 글
camelCase 요청 데이터를 snake_case로 변환하기 (0) | 2024.11.05 |
---|---|
snake_case 응답 데이터를 camelCase로 변환하기 (0) | 2024.11.04 |
[React] React Router 총정리 (0) | 2024.08.26 |
[React] Vite + TypeScript + PWA 프로젝트 생성하기 (1) | 2024.07.30 |