React - Quill 에디터로 저번 프로젝트 때 사용을 했었는데
기본 에디터 기능은 다 동작을 했었지만 이미지를 올렸을 때 리사이저로 이미지 크기를 조절했었는데
그 때 이미지가 2개가 되버리면 리사이저가 제대로 동작을 안하는 일이 있었고 또한 에디터상에서 이미지를
바로 올려버리면 base64로 처리가돼 아주 긴 문자열로 DB에 저장되게 된다.
그러한 이유때문에 직전 프로젝트에서 이미지기능과 동영상기능을 둘 다 사용하지않고 끝냈었던 기억이있는데
너무 아쉬웠고 또 앞으로 에디터를 계속 사용할터이기에 이번 기회에 해결하려고 해보았다
그래서 간단한 에디터 연습용 코드를 짜보았는데
우선 들어가기에 앞서
yarn add react-quill 로 react-quill 에디터 라이브러리를 설치해주었고 이미지를 조절하기위해 quill-image-resize
라이브러리를 설치했는데 이녀석은 @types/로 타입까지 설치를 지원안하는듯해서
src폴더에 @types라는 디렉토리를 추가하고 그 안에 quill-image-resize.d.ts 파일을 생성하고
declare module "quill-image-resize" {
import { Quill } from "react-quill";
class ImageResize {
constructor(quill: Quill, options?: any);
}
export default ImageResize;
}
요렇게 모듈을 정의해주었다
일단 기본적인 리사이저까지는 이렇게 설치를했고
import React, { useState, useMemo, useRef, useEffect } from "react";
import "react-quill/dist/quill.snow.css";
import ReactQuill, { Quill } from "react-quill";
import ImageResize from "quill-image-resize";
Quill.register("modules/ImageResize", ImageResize);
interface EditorProps {
value: string;
onChange: (content: string) => void;
}
const Editor: React.FC<EditorProps> = ({ value, onChange }) => {
const quillRef = useRef<ReactQuill | null>(null);
const [content, setContent] = useState(value);
const modules = useMemo(() => {
const Parchment = Quill.import("parchment");
return {
toolbar: {
container: [
[{ header: [1, 2, 3, false] }],
["bold", "italic", "underline", "strike"],
["blockquote"],
[{ list: "ordered" }, { list: "bullet" }],
[{ color: [] }, { background: [] }],
[{ align: [] }, "link"],
["image", "video"],
],
},
ImageResize: {
parchment: Parchment,
},
};
}, []);
// 에디터 내용이 바뀔 때마다 부모 컴포넌트로 업데이트 전달
useEffect(() => {
onChange(content);
}, [content, onChange]);
return (
<div>
<ReactQuill
style={{ width: "450px", height: "300px" }}
placeholder="내용을 입력해주세요"
theme="snow"
ref={quillRef}
value={content}
onChange={setContent}
modules={modules}
/>
</div>
);
};
export default Editor;
에디터 컴포넌트도 이렇게 정의를 해주었다
그러고 Post 컴포넌트를 작성해주었는데
import React, { useState } from "react";
import Editor from "../Editor/Editor";
const Post = () => {
const [content, setContent] = useState<string>("");
const handleContentChange = (newContent: string) => {
setContent(newContent);
};
return (
<div>
<Editor value={content} onChange={handleContentChange} />
<h2 style={{ marginTop: "100px" }}>작성된 내용:</h2>
<div dangerouslySetInnerHTML={{ __html: content }} />
</div>
);
};
export default Post;
요렇게
<div dangerouslySetInnerHTML={{ __html: content }} />
이 코드를 넣어주어야 에디터상에서 글씨를 입력하면 그 안에 코드가 <br>태그나 스타일을 넣는다면
style 태그들이 들어있게되는데 이를 dangerouslySetInnerHtml로 해주어야 그 안의 내용이 다 스타일이
적용되어서 디스플레이된다
리사이저도 잘 동작하는 모습을 확인할 수 있었고
동영상도 올라가긴 잘 올라가는데 리사이저로 크기를 조절하는 걸 해보아야겠다