내일배움캠프 TIL

내일 배움 캠프 23_08_02 TIL

짱구도난말려 2023. 8. 2. 20:32

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로 해주어야 그 안의 내용이 다 스타일이

적용되어서 디스플레이된다

 

리사이저도 잘 동작하는 모습을 확인할 수 있었고 

 

동영상도 올라가긴 잘 올라가는데 리사이저로 크기를 조절하는 걸 해보아야겠다