라이브러리/SunEditor-react

[suneditor-react] suneditor 이미지 업로드 리팩토링

눙엉 2023. 10. 27. 12:34

SunEditor를 사용해서 공지사항 WYSIWYG 기능을 구현하고 있었고, 이미지 업로드 리팩토링이 필요해서 정리해 두면 좋을 것 같았다.

 

Editor를 사용해서 글을 작성하면 HTML로 이루어진 코드를 확인할 수 있다.

글 작성과 함께 추가한 이미지는 base64로 인코딩 되어 HTML코드에 입력된다.

인코딩 된 base64 데이터는 이미지의 품질을 떨어뜨리고 데이터 크기를 늘어나게 하는 단점이 있어서 추가한 이미지는 S3로 업로드하고 업로드된 주소를 HTML코드의 img 태그 src속성에 치환하여 저장했다.

 

기존 로직

  1. Editor에 글, 이미지 작성(HTML 코드로 작성됨)
  2. 이미지 추가 -> 글과 별개로 상태 값에 File 객체 추가 (상태값 2개 관리)
  3. 이미지 추가, 수정 될 때마다 File 객체 상태값 수정
  4. 작성한 글을 POST요청 할 때 파일 객체들을 S3에 업로드
  5. S3에 업로드 후 반환 받은 이미지가 저장된 주소를 작성해 둔 img src에 base64로 인코딩 되어 있던 코드와 교체
  6. Editor에 작성한 HTML 코드 서버에 저장

 

문제점

  • Editor로 작성한 HTML 코드, File 객체를 상태 값으로 따로 관리 -> 관리해야 되는 데이터가 2개
  • 이미지가 추가 되거나 순서가 변경되는 등 이미지를 수정 -> File 객체 상태를 수정해야 된다.

 

관리해야 되는 데이터가 많아지고 로직이 복잡해질수록 에러가 발생할 가능성이 높아진다.

 

수정 로직

  1. Editor에 글, 이미지 작성(HTML 코드로 작성됨)
  2. 이미지 추가 -> 글과 별개로 상태 값에 File 객체 추가 (상태값 2개 관리)
  3. 이미지 추가, 수정될 때마다 File 객체 상태값 수정
  4. 작성한 글을 POST요청할 때 파일 객체들을 S3에 업로드
  5. S3에 업로드 후 반환받은 이미지가 저장된 주소를 작성해 둔 img src에 base64로 인코딩 되어 있던 코드와 교체
  6. Editor에 작성한 HTML 코드 서버에 저장

 

import { v4 as uuidv4 } from "uuid";

// base64로 인코딩 되어 있는 이미지를 File 객체로 변환하는 함수
const makeBase64ImageToFile = (base64Image: string) => {
  const mimeType = base64Image.split(";")[0].split(":")[1];
  const extension = mimeType.split("/")[1];
  const byteString = atob(base64Image.split(",")[1]);
  const arrayBuffer = new ArrayBuffer(byteString.length);
  const uint8Array = new Uint8Array(arrayBuffer);

  for (let i = 0; i < byteString.length; i++) {
    uint8Array[i] = byteString.charCodeAt(i);
  }

  const blob = new Blob([arrayBuffer], { type: mimeType });
  const fileName = `${uuidv4()}.${extension}`;
  const file = new File([blob], fileName, { type: mimeType });

  return { file, fileName };
};


// Editor에서 작성한 HTML 코드를 복사 후 이미지 주소 치환 후 서버에 저장용
let editorContent = htmlCode;

const base64ImageRegex = /<img src="(data:image\/[^;]+;base64[^"]+)"/g;

while ((match = base64ImageRegex.exec(htmlCode)) !== null) {
  // Editor로 작성한 글에서 base64로 인코딩 되어 있는 이미지 검색
  const base64Image = match[1];

  // base64로 인코딩 되어 있는 이미지 -> File 객체로 변환
  const { file, fileName } = makeBase64ImageToFile(base64Image);

  const { status } = await S3에 이미지 업로드(file);

  if (status !== 204) return null;
  
  // AWS S3서버에 저장된 이미지 주소를 img src의 속성으로 치환
  editorContent.replace(base64Image, 이미지 저장 주소);
}

 

while문에서 HTML 코드의 base64로 인코딩 되어 있는 img 태그를 찾아 File 객체로 변환하여 S3서버에 업로드한다.

업로드 후 이미지가 저장되어 있는 주소를 반환받아 작성한 HTML코드에 img 태그의 src 속성으로 치환해 주었다.

 

File 객체를 따로 관리할 필요도 없고 이미지를 추가, 수정할 때마다 File 객체 상태에서 File 객체의 순서를 수정할 필요도 없어진다.

 

관리해야 되는 상태 값을 한 개로 줄이고, 작업해야 되는 로직이 줄어 뜸으로써 에러를 발생시킬 가능성을 낮출수 있다.

'라이브러리 > SunEditor-react' 카테고리의 다른 글

[suneditor-react] suneditor 사용법  (14) 2022.11.19