[React] wysiwyg 에디터 사용기, quill 에러부터 react-draft-wysiwyg

D uuu·2023년 12월 3일
1

React

목록 보기
5/10

React wysiwyg 에디터

어드민 페이지에서 공지사항 게시글을 쓰는 부분에 텍스트 에디터를 적용하기로 했다. 텍스트 에디터를 처음 사용해보는거라 어떤 에디터가 있는지부터 알아봐야했고, 그 중 내가 필요한 기능에 적합한 에디터를 추려내보기로 했다.

필요기능

  • 한국어 지원
  • 사진 및 표 첨부
  • 폰트 변경 가능
  • 쉬운 조작 (doc, community 활성화)

찾아보니 아래 3가지 에디터가 가장 많이 보여 npm trends 에 다운로드수를 먼저 검색해봤다. 리액트에서 사용하기 때문에 모두 react 버전으로 검색했다.

  • 다운로드 수 기준 : react-quill > react-draft-wysiwyg > toast-ui/react


React-quill

다운로드수가 압도적으로 많았던 quill 에 대해 먼저 찾아보니, 내가 필요한 기능들을 대체적으로 지원하고 있었다. 그래서 설치 후 사용해봤는데, 다른 문제가 발생했다.

아래 경고 메시지가 콘솔에 뜨기 시작한 것이다..!

[Deprecation] Listener added for a synchronous 'DOMNodeInserted' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead.

문제를 해결하려면 경고 메시지 이해가 먼저 필요했다.

  1. Mutation Events

Mutation Events 는 동기적으로 작동 하는데, 이 이벤트가 호출될때 다른 이벤트가 실행되지 않을 수 있다고 한다.

더군다나 MDN 을 찾아보니 이 기능은 더 이상 권장하지 않으며, event listener 을 추가하면 DOM 성능이 크게 저하된다고 (속도가 1.5~7배 정도 느려짐) 나와있다. 이러한 이유로 인해 크롬에서는 24년도부터는 사용을 중지할 거라고도 한다..
경고 메시지에서는 Mutation Events 대신 MutationObserve 을 사용하라고 나와있는데,

  1. Mutataion Observer

Mutataion Observer 는 비동기적으로 동작하는데, DOM 변경 사항을 모니터링(observer) 하면서도 성능을 유지할 수 있다고 한다.


<문제되는 코드>

      var Scroll = function (_Parchment$Scroll) {
        _inherits(Scroll, _Parchment$Scroll);
        function Scroll(domNode, config) {
          _classCallCheck(this, Scroll);
          var _this = _possibleConstructorReturn(this, (Scroll.__proto__ || Object.getPrototypeOf(Scroll)).call(this, domNode));
          _this.emitter = config.emitter;
          if (Array.isArray(config.whitelist)) {
            _this.whitelist = config.whitelist.reduce(function (whitelist, format) {
              whitelist[format] = true;
              return whitelist;
            }, {});
          }
          // Some reason fixes composition issues with character languages in Windows/Chrome, Safari
          _this.domNode.addEventListener('DOMNodeInserted', function () {});
          _this.optimize();
          _this.enable();
          return _this;
        }

위에 코드를 보면 DOMNodeInserted 부분을 볼 수 있다. 바로 저거 때문에 경고 메시지가 뜨는 것 같다. 그럼 경고 메시지에서 알려준대로 MutataionEvents 를 MutationObserve 로 대체하면 될까 ?


github 에 이미 이 이슈가 올라와있었는데, 상당히 오래전부터 이 이슈에 대해 논의가 오갔던 거 같다.

https://github.com/quilljs/quill/issues/1768

#luin (quill 개발담당자?) 가 답글을 달았는데, 2.0 버전에서는 mutation event 사용부분을 제거했다고 하는데, 여전히 경고 메시지가 뜨고 있다ㅠㅠ
구글링을 계속 해봤지만, 결국 해결 방법을 찾지 못했다.

https://github.com/quilljs/quill/issues/3806

보다시피 2.0 을 사용하고 있다..!!

에디터를 바꾸자

고민이 되었다. 다른 방법이 있는데, 내가 찾지 못하는 건 아닐까? 경고 메시지를 무시하고 계속 사용하는게 맞을까?

그런데 그러기엔 너무 찝찝했다. 이미 오래전부터 이슈가 논의중에 있었으나 아직 해결이 안된걸로 봐서는 개선 여지가 불투명해보였고, 아직 프로젝트 초기 단계이니 바꿔도 지금 바꾸는게 낫다는 판단이 섰다.



react-draft-wysiwyg

react-draft-wysiwyg 는 draft js 를 사용하기 쉽게 리액트로 구성한 것이다. (draft js 는 페이스북에서 운영하는 text rich 에디터이다)
따라서 draft-js 도 같이 설치해줘야 한다. 이걸 모르고 react-draft-wysiwyg 만 설치했더니 계속 에러가 났다.

npm install react-draft-wysiwyg draft-js



리액트를 문법에 익숙하다면 크게 어렵지 않게 구현할 수 있다.

코드보기🔻

const [editorState, setEditorState] = useState(EditorState.createEmpty());

 const onEditorStateChange = (editorState) => {
    setEditorState(editorState);
  };
  
  (생략)
  
    <Editor
          placeholder="내용을 작성해주세요."
          localization={{
            locale: "ko",
          }}
          toolbar={{
            image: { uploadCallback: uploadCallback },
          }}
          editorState={editorState}
          onEditorStateChange={onEditorStateChange}
          editorStyle={{
            height: "400px",
            width: "100%",
            border: "3px solid lightgray",
            padding: "20px",
          }}
        />

editorState 를 콘솔에 찍어보면 아래와 같이 객체 형태로 나오는데, 이 값을 HTML 태그 형태로 변경해주려면 draftjs-to-html 을 따로 설치해야 한다.

npm install draftjs-to-html

👇 그래서 최종 코드는 아래와 같다.

const [editorState, setEditorState] = useState(EditorState.createEmpty());
const [htmlString, setHtmlString] = useState("");
  
 
const onEditorStateChange = (editorState: any) => {
  setEditorState(editorState);
  const html = draftjsToHtml(convertToRaw(editorState.getCurrentContent()));
    setHtmlString(html);
  };
  
  (생략)
  
    <Editor
          placeholder="내용을 작성해주세요."
          localization={{
            locale: "ko",
          }}
          toolbar={{
            image: { uploadCallback: uploadCallback },
          }}
          editorState={editorState}
          onEditorStateChange={onEditorStateChange}
          editorStyle={{
            height: "400px",
            width: "100%",
            border: "3px solid lightgray",
            padding: "20px",
          }}
        />
     <div dangerouslySetInnerHTML={{ __html: htmlString }}></div>


아직 끝이 아니다..

이제 데이터를 서버로 보내는 작업이 필요하다. 또한 react-draft-wysiwyg 은 이미지 업로드 기능도 제공하기 때문에 이미지를 넣었을때 서버쪽으로 보내는 작업도 해야하고, 게시글 수정 기능 등등 해야할게 아직 많다. 서버가 아직 만들어지지 않은 상태라 우선 기능만 구현해놓고 나머지는 차차 진행해야겠다.

이번에 처음으로 텍스트 에디터를 사용해봤는데, 역시 자주 사용하는 기능이라 그런지 라이브러리도 잘 되어 있고 생각보다 쉽게 따라할 수 있었다.
다만, quill 에러로 인해 찾아보느라 시간을 많이 썼으나 덕분에 두가지 라이브러리를 사용해 볼 수 있는 좋은 기회였다.




도움받은 사이트
https://haranglog.tistory.com/12
https://velog.io/@yjlim0428/React-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%97%90%EB%94%94%ED%84%B0-%EB%B9%84%EA%B5%90

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글

Powered by GraphCDN, the GraphQL CDN