반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

@toast-ui/react-editor 적용하기(Dockerizing 시 종속성 문제 해결) 본문

UpLog 릴리즈노트 프로젝트

@toast-ui/react-editor 적용하기(Dockerizing 시 종속성 문제 해결)

5_hyun 2023. 8. 25. 02:32

다크 모드가 실행되는 에디터 컴포넌트

import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { Editor } from '@toast-ui/react-editor';
import '@toast-ui/editor/dist/toastui-editor.css';
import colorSyntax from '@toast-ui/editor-plugin-color-syntax';
import 'tui-color-picker/dist/tui-color-picker.css';
import '@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css';
import '@toast-ui/editor/dist/i18n/ko-kr';

import '@toast-ui/editor/dist/toastui-editor.css';
import '@toast-ui/editor/dist/theme/toastui-editor-dark.css';

import 'prismjs/themes/prism.css';
import '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css';
import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight';
import Prism from 'prismjs';

import 'prismjs/themes/prism.css';
import 'prismjs/themes/prism-okaidia.css'; // 다크 모드 테마를 추가합니다
import '@toast-ui/editor/dist/theme/toastui-editor-dark.css'; // Toast UI 에디터 다크 모드 테마를 추가합니다

import 'prismjs/components/prism-jsx.min'; // JSX 언어 지원을 포함합니다 (선택 사항)

import 'prismjs/plugins/line-numbers/prism-line-numbers.css'; // 코드 블럭에 줄 번호를 추가하기 위해 이 줄을 추가합니다
import 'prismjs/plugins/line-numbers/prism-line-numbers.min';
import { useRecoilState } from 'recoil';
import { themeState } from '@/recoil/Common/atom.ts'; // 줄 번호 플러그인을 포함합니다
export default function PostEditor() {
  const editorRef = useRef<Editor>(null);
  const [darkMode, setDarkMode] = useRecoilState(themeState);

  const onChange = () => {
    const data = editorRef!.current!.getInstance().getHTML();
    console.log(data);
    // console.log(editorRef!.current!.getRootElement().clientHeight);
  };

  const onUploadImage = async (blob: Blob, callback: (url: string, altText: string) => void) => {
    console.log(blob);

    // 이건 로컬에서만 가능
    callback(URL.createObjectURL(blob), '사진');

    // TODO: 이미지 스토리지 완성되면 연결
    // const url = await uploadImage(blob);
    // callback(url, 'alt text');
    // return false;
  };

  /** editor 다크 모드 */
  // 그냥 useEffect로 하면 에디터가 흰색이었다가 검정으로 바뀌는게 너무 신경쓰임
  useLayoutEffect(() => {
    const editorEl = document.getElementsByClassName('toastui-editor-defaultUI')[0];

    if (editorEl) {
      const shouldAddDarkClass = darkMode && !editorEl.classList.contains('toastui-editor-dark');
      const shouldRemoveDarkClass = !darkMode && editorEl.classList.contains('toastui-editor-dark');

      if (shouldAddDarkClass) {
        editorEl.classList.add('toastui-editor-dark');
      } else if (shouldRemoveDarkClass) {
        editorEl.classList.remove('toastui-editor-dark');
      }
    }
  }, [darkMode]);

  return (
    <Editor
      height="90vh"
      initialEditType="wysiwyg"
      ref={editorRef}
      // toolbarItems={[
      //   ['bold', 'italic', 'strike'],
      //   ['hr'],
      //   ['image', 'link'],
      //   ['ul', 'ol'],
      //   ['code', 'codeblock'],
      // ]}
      hideModeSwitch={true}
      useCommandShortcut={false}
      plugins={[colorSyntax, [codeSyntaxHighlight, { highlighter: Prism }]]}
      language="ko-KR"
      onChange={onChange}
      hooks={{
        addImageBlobHook: onUploadImage,
      }}
    />
  );
}

우선 공식 문서와 여러 블로그들을 참고하면서 Editor 컴포넌트를 만들었다.

이 코드에서 Editor 태그 안에 toolbarItems는 위 사진에서 보이는 글의 toolbar를 커스텀 할 수 있는 코드이다.

다크 모드도 적용되게 해놨는데, useLayoutEffect 안에 있는 코드가 다크 모드 전환 시 적용되는 코드이다. 라이브러리 자체에서 제공하는 방법은 적용되지 않기 때문에, toastui-editor-dark이 class를 넣고 빼는 식으로 구현했다. 

useLayoutEffect로 구현한 이유는 그냥 useEffect로 하면 새로고침 시 다크 모드 색 전환이 좀 느리게 되는 경향이 있어서, 렌더링 전에 처리하기 위해 useLayoutEffect를 사용했다.


Dockerizing 시 발생하는 문제점

Editor를 가장 최신 버전으로 설치하고 배포하면 이런 에러가 발생한다.

이 문제점은 https://github.com/nhn/tui.editor/issues/2631 깃허브 issue에도 올라와 있다고 한다.

이 라이브러리는 react 17에 의존성을 가지는데, 나는 react 18 버전을 사용해서 에러가 발생하는 것 같다.

 

-해결법

"dependencies": {
    "@toast-ui/react-editor": "3.1.8",
}
"resolutions": {
    "@toast-ui/editor": "3.1.8",
 }

package.json에서 위 코드처럼 버전을 낮추고, resolutions 필드를 설정했다.

resolutions을 사용해 하위 패키지의 버전을 명시할 수 있다.

 

이렇게 수정하고 배포하니 Dockerizing 환경에서도 잘 동작했다!

다음부터는 사용하려는 라이브러리가 react 어떤 버전까지 지원하는지 꼭 확인하고 사용해야겠다고 느꼈다. 로컬 환경에서는 잘 돌아 갔지만 Docker에서 제대로 돌아가지 않아서 매우 당황했었다...!

 

-참고 글

https://velog.io/@giriboy/TOAST-UI-Editor-%EB%8F%84%EC%9E%85%EA%B8%B0

 

TOAST UI Editor 도입기

대부분의 개발자들은 markdown으로 글을 작성하는 것이 편하다고 느낄 것이다.마찬가지로 레벨로그를 작성할 때도 markdown을 지원하는 것이 사용할 때도 편할 것 같아 마크다운 지원 에디터를 도입

velog.io

https://velog.io/@ongsim123/Devlog-Toast-ui-Editor-%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

[Devlog] Toast ui Editor 다크모드 만들기

Recoil을 이용해 라이트/다크모드를 관장하는 state를 관리했었다.사용자의 다크모드 ↔️ 라이트모드 버튼 클릭에 따라, darkState를 바라보는 모든 컴포넌트는 토글되는 로직으로 구현했는데, Toast

velog.io

https://leego.tistory.com/entry/React-%EC%97%90%EB%94%94%ED%84%B0%EB%A1%9C-TOAST-UI-Editor-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0

 

React 에디터로 TOAST UI Editor 사용해보기

프로젝트에 쓸 에디터 선정에 많은 고민을 했다. React 사용자들이 주로 사용하는 에디터를 조사해서 몇 가지로 추려내었다. 에디터 선정을 위한 기준은 다음과 같았다. 직관적인 UI 사용자가 개

leego.tistory.com

 

728x90
반응형
Comments