ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TinyMCE] 이미지와 텍스트가 섞인 게시글 작성하기
    React.js/라이브러리 2023. 12. 13. 17:12

     

     

     

     

     

    해당 에디터에서 이미지를 삽입 후 콘솔에 값을 띄워보면 base64로 변환되어 있는 것을 확인했다.

    base64가 오지게 길어서 서버에 그대로 보낸다면 부담이 될 것 같아서 방법을 찾아봤다.  

     

     

     

     

    import { Editor } from '@tinymce/tinymce-react';
    import { useEffect, useRef } from 'react';
    import { imageConversion } from '../../api/boards';
    
    const editor_api = import.meta.env.VITE_EDITER_API_KEY;
    
    export const TinyEditor = ({ value, handleContent }) => {
      const editorRef = useRef();
    
      useEffect(() => {
        const handleEditorInit = (editor) => {
          editorRef.current = editor;
        };
    
        if (editorRef.current) {
          handleEditorInit(editorRef.current);
        }
      }, []);
    
      const handleImageSelection = async (event) => {
        const file = event.target.files[0];
        const imageUrl = await imageConversion(file);
    
        const currentEditor = editorRef.current;
        if (currentEditor) {
          currentEditor.execCommand('mceInsertContent', false, `<img src="${imageUrl}" alt="Inserted Image" />`);
        }
      };
    
      const addImage = () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'image/*';
        input.onchange = handleImageSelection;
        input.click();
      };
    
      return (
        <Editor
          apiKey={editor_api}
          value={value}
          onInit={(ent, editor) => (editorRef.current = editor)}
          onEditorChange={(content) => {
            handleContent(content);
          }}
          init={{
            placeholder: '내용을 입력하세요',
            language: 'ko_KR',
            selector: 'textarea',
            menubar: false,
            height: '70vh',
            plugins: [
              'advlist',
              'autolink',
              'lists',
              'link',
              'image',
              'charmap',
              'preview',
              'anchor',
              'searchreplace',
              'visualblocks',
              'code',
              'fullscreen',
              'insertdatetime',
              'media',
              'table',
              'code',
              'help',
              'wordcount',
              'save',
            ],
            toolbar:
              'formatselect fontselect fontsizeselect |' +
              ' forecolor backcolor |' +
              ' bold italic underline strikethrough |' +
              ' alignjustify alignleft aligncenter alignright |' +
              ' bullist numlist |' +
              ' table tabledelete |' +
              ' link custom_image |' +
              ' insertimage',
            fontsize_formats: '9px 10px 11px 12px 13px 14px 15px 16px 18px 20px 22px 24px 28px 32px 36px 48px',
            content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }',
    
            setup: (editor) => {
              // 이미지 삽입 버튼 클릭 시 이미지 선택 다이얼로그 열도록 설정
              editor.ui.registry.addButton('insertimage', {
                icon: 'image',
                tooltip: 'insert image',
                onAction: addImage,
              });
            },
          }}
        />
      );
    };

     

    export const imageConversion = async (file) => {
      const formData = new FormData();
      formData.append('image', file);
    
      try {
        const result = await axios.post('/api/images', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        });
        return result.data.imgUrl;
      } catch (error) {
        console.error(error);
      }
    };

     

     

     

    1. 에디터에 이미지 삽입 옵션을 넣고, 이미지를 업로드 했을 때 실행되는 함수 addImage를 정의했다.

    2. add된 이미지가 바뀔 때 마다 handleImageSelection 함수를 실행시킨다.

    3. handleImageSelection 함수는 파일을 받아서 서버에 formData 형식으로 요청한 후, 응답값인 이미지 URL을 에디터에 바로 띄우는 로직을 수행한다.

    4. 현재 커서 위치에 해당 이미지 태그가 삽입된다.

     

     

     

     

     

    댓글