본문 바로가기
개발(Development)/React(리액트)

[React] Toast-UI Editor 이미지 파일 서버 업로드 방법 (base64 인코딩 X)

by 카레유 2022. 5. 16.

# Toast-UI Editor 이미지 파일 서버 업로드 방법

일반적으로 이미지를 관리하는 방식은

첨부 이미지 파일은 서버 디스크에 저장해두고, 해당 경로만 DB에 저장해두는 것이다.

 

그러나 Toast-UI Editor 에서 이미지를 첨부하면

img 태그의 src에 이미지 데이터 전체가 base64로 인코딩 되어 주입된다.

 

Markdown 의 경우에도 형식은 다르지만 결과적으로 동일하다.

 

만약  이 상태 그대로 DB에 저장해두면,

레코드 한 줄마다 몇 Mb씩 차지하는 곤란한 상황이 발생할 수 있다.

 

우리가 원하는 건.

 

1. 이미지 파일은 서버로 전송하고,

2. 파일이 저장된 경로만 DB에 저장해두고, img 태그의 src 속성값으로 사용하는 것

 

일 것이다.

 

지금부터 Toast-UI Editor 에서 첨부한 이미지를 File 객체에 담아서 다루는 방법을 정리한다.


[ 원리 ] 

- Toast-UI Editor는 이미지가 첨부될 때,

  (이미지 첨부 창에서 OK를 누르거나, 에디터에 이미지를 드래그 할 때)

- addImageBlobHook 이라는 녀석을 작동시킨다.

- 바로 이 때 !!! addImageBlobHook 녀석을 통해 이미지를 가로채서 서버에 전송해 주면 된다.

 

 

 

[ addImageBlobHook 이란? ]

=> 첨부된 이미지를 File객체로 받고, img 태그의 src 와 alt 속성을 설정해 화면에 표시하는 역할을 한다.

 

- 상세한 구조는 아래와 같다.

type HookCallback = (url: string, text?: string) => void;

export type HookMap = {
  addImageBlobHook?: (blob: Blob | File, callback: HookCallback) => void;
};

 

즉, addImageBlobHook(blob, callback) 형태를 가진다.

 

1. blob:  첨부된 이미지를 File 객체 형태로 받는다.

2. callback(url, string): img 태그를 만들어 화면에 이미지를 표시한다.

  - 인자로 받은 url(이미지 경로)를 img태그의 src에 주입하고, text인자로 받은 값은 alt에 주입한다.

 

이를 참고하면,  

addImageBlobHook의 디폴트 동작 방식을 알 수 있다.

 

1) blob인자로 받은 첨부 이미지를  base64 인코딩한다.

2) 콜백함수를 호출시키면서 img 태그의 src에 인코딩된 이미지 데이터를 주입하고,

3) 아래의 description으로 입력받은 text를 alt에 주입한다.

4) 완성된 img태그를 화면에 삽입하여 표시한다.

 

이제 답은 나왔다.

blob인자로 받은 첨부 이미지를 base64로 인코딩하게 놔두지 않고,

개발자가 직접 서버로 전송해주면 되는 것이다.

 

 

 

addImageBlobHook 사용 방법 

- blob인자로 입력받은 첨부 파일을 서버로 전송하고,

- callback 함수를 호출시켜 img 태그의 src, alt 속성을 설정해 화면에 표시해주면 된다.

- 이를 위해 Editor 컴포넌트의 hooks 프롭에서 addImageBlobHook을 설정해주면 된다.

 

* 아래 코드를 보면 바로 이해된다에 한표 드립니다!

 

주의할 점은. 서버 통신을 위해 async/await 를 사용했다는 점이다.

import { useRef } from 'react';

// Toast 에디터
import { Editor } from '@toast-ui/react-editor';
import '@toast-ui/editor/dist/toastui-editor.css';

export default function ToastEditor() {
  // Editor DOM
  const editorRef = useRef();

  return (
    <div>
      <Editor
        ref={editorRef}
        placeholder="내용을 입력해주세요."
        previewStyle="vertical"
        height="300px"
        initialEditType="wysiwyg"
        toolbarItems={[['bold', 'italic', 'strike'], ['image']]}
        
        // hooks 에서 addImageBlobHook 를 주물러 주면 된다.
        hooks={{
          addImageBlobHook: async (blob, callback) => {
            
            console.log(blob);  // File {name: '카레유.png', ... }

            // 1. 첨부된 이미지 파일을 서버로 전송후, 이미지 경로 url을 받아온다.
            // const imgUrl = await .... 서버 전송 / 경로 수신 코드 ...

            // 2. 첨부된 이미지를 화면에 표시(경로는 임의로 넣었다.)
            callback('http://localhost:5000/img/카레유.png', '카레유');
          }
        }}
      ></Editor>
    </div>
  );
}

 

blob을 콘솔에 찍어보면, 첨부된 이미지가 File 객체로 들어왔음을 알 수 있다.

또한 callback 을 통해 생성된 img 태그도 정상적으로 표시된다.

 

 

파일을 서버로 전송하는 방법은

File 객체를 FormData 등에 첨부하여 fetch나 axios 를 통해 전송하면 되는 부분으로 생략한다.


실제 구현 시에는 다양한 방식을 조합해서 개발해야겠지만,

이 글이 약간의 도움이라도 되셨길 바랍니다.

 

이미지 첨부 자체를 막는 방법은 아래 글을 참고.

[React] Toast-UI Editor 이미지 업로드/드래그 첨부 막기 방법

 

 

 

댓글