CKEditor 4 버전의 이미지 업로드 방식은 꽤나 복잡하다.
이미지 업로드 버튼을 누르면 이렇게 꽤나 구린 레이어 팝업이 뜨는데
여기서 파일 선택을 누르면 업로드할 이미지 파일을 선택할 수 있다.
파일을 선택하고 나서 난 계속 습관적으로 확인을 누른다.
근데 서버로 전송을 먼저 누르지 않으면 확인 버튼을 눌렀을때 이미지 등록이 그냥 취소된다 ㅎ
그리고 이미 적용한 이미지의 크기를 변경해야할 때도
보통 다른 에디터에서 제공하는 것처럼.. 이미지의 모서리를 드래그해서 조절하는 게 아니라
이미지를 더블클릭해서 나오는 아래 팝업에서 너비를 직접 숫자값으로 입력해서 조절한다.
CKEditor5에서는 이러한 이미지 첨부 관련 기능이 많이 개선되었다.
게다가 CKEditor4는 2023년 6월부로 지원이 종료됐다고 한다.
그래서 5버전으로 올리려고 했는데… 이 버전업을 할때 꽤나 바뀐게 많아서 버전업 하는 데 엄청 삽질했다.
일단 프로젝트 환경은 react나 vue 이런걸 안쓰고 그냥 html 엔진을 쓰고 있었기 때문에 node 같은 건 안쓴다
4버전의 경우는 문제가 없었다. 그냥 JS방식의 파일 패키지를 통으로 받으면 되니까...
근데 5버전의 경우 node로 개발되어.. npm 방식으로 플러그인들을 add하는 방식이었다.
참고로 난 node js에 익숙하지 않다 ㅜ
주요 이슈가 이미지 관련이었으므로 이걸 적용한 버전이 필요했다.
그래서 5버전으로 업그레이드 하기로 했고.. 5버전에서 이미지 업로드를 지원하는 방식은 4개정도 있었는데
그 중 무료이고, Base64 바이너리가 아니라 파일로 업로드하는 방식인 SimpleImageAdapter를 선택했다.
이걸 적용하기 위해 두 가지 방법을 시도해 봤는데
- CDN을 사용한다.
- cdn으로 간단하게 5버전으로 마이그레이션 할 수 있으려나?했는데 전혀 아니었다. 우선 cdn같은 경우는 커스터마이징이 안된다. 근데 이 cdn에는 SimpleImageAdapter가 포함되어 있지 않았다. (계속 플러그인을 못 찾는다고 오류남)
- 그래서 CDN 사용은 포기
- online builder를 사용한다.
- 내가 사용하고 싶은 플러그인을 ckeditor에서 제공하는 online builder에서 선택하면 얘네가 자체적으로 내가 선택한 플러그인으로 소스를 빌드해서 js파일로 다운받을 수 있게 제공해 준다.
- 난 여기서 classic editor를 고르고 이것저것 플러그인을 넣어서 다운받았다.
- 그런다음 다운받은 압축파일을 풀어서 소스에 통으로 붙여넣고,, build/ckeditor.js 파일을 import해서 사용하려 했다.
- 이미지 업로드 플러그인으로 SimpleImageAdapter를 사용했는데 이거 관련 설정이 계속 꼬였다. URL 설정이 틀리다거나 계속 required plugin이 빠져있다거나 하는..
- 그래서 중간에 다시 4버전으로 돌리고 4에서 이미지 첨부쪽만 개선한 플러그인이 없을까 알아봤는데.. easyimage라는 플러그인이 있었는데 유료기도 했고 이미지가 우리 서버가 아니라 ck 클라우드 서버에 올라간다 해서 원하는 방식이 아니었다.
- 어찌저찌 설정을 만지다 보니 설정을 완료했다 ;;
online builder로 성공한 방법
- 일단 아래 링크로 가서 원하는 기능을 다 고른 후 download 했다.
- 다운받은 폴더를 통으로 일단 스프링 소스에 넣었다. 계속 동작확인을 해가면서 개발해야 했기 때문..
- 우선 처음 이 파일을 적용하니까 simple image 기능은 들어갔지만 툴바에 아이콘이 아예 없고 textarea에 글도 안 써졌다.
- 다음을 적용해서 해결했다.
- 툴바 아이콘 없는 문제
- 툴바 아이콘이 세팅되기 전에 editor 객체부터 생성되어서 생긴 문제 같았다.
- 구글링 끝에 위 소스를 찾아서 적용하니 툴바 적용이 완료됐다.
- 참고: https://ckeditor.com/docs/ckeditor5/latest/installation/integrations/react.html#using-the-document-editor-build
-
ClassicEditor.create(document.querySelector( '#desc' ), { plugins: [ ... "Underline", ... ], ...
- 글이 안 써지는 문제
- 툴바 아이콘 없는 문제
- 이 두 문제를 해결한 다음 simple image 설정을 했다.
ClassicEditor.create(document.querySelector( '#desc' ), { plugins: [ ... "SimpleUploadAdapter", ... ], ... simpleUpload: { toolbar: ['imageTextAlternative'], uploadUrl: '/admin/upload/ckeditor', withCredentials: true }, image: { toolbar: [ 'imageTextAlternative', 'linkImage' ] }, ... } ) .then( newEditor => { newEditor.ui.getEditableElement().parentElement.insertBefore( newEditor.ui.view.toolbar.element, newEditor.ui.getEditableElement() ); window.ckeditor = newEditor; } ) .catch( error => { console.error( error ); } );
- 설정을 하니까 이미지 첨부는 바로 되는데 제일 원했던 기능인 resizing이 안돼서 resize 관련 플러그인도 별도 설치했다.
- 아마 Image,ImageEditing,ImageResize,ImageResizeEditing,ImageResizeHandles 이렇게 있으면 되는 것 같은데 저중 없어도 되는 게 있을 수도 있다.. 난 다 설치했다
- https://ckeditor.com/docs/ckeditor5/latest/api/module_image_imageresize_imageresizehandles-ImageResizeHandles.html
- 플러그인 설치 방법
- 플러그인은 npm 명령어로 설치해야 하므로 pc에 node js가 설치되어 있어야 한다.
- 다운받은 소스에서 루트경로/src/ckeditor.js 파일을 연다
- 추가하고자 하는 플러그인을 해당 소스에 import해준다.
- import할 주소는 공식문서를 참고한다.
- 예를 들어 Underline 플러그를 설치하고 싶으면 공식 문서에서 underline을 검색한다.
- 결과 페이지 (https://ckeditor.com/docs/ckeditor5/latest/api/module_basic-styles_underline-Underline.html) 에서 플러그인명 아래의 주소 (@ckeditor/ckeditor5-basic-styles/src/underline) 뒤에 .js를 붙여 import할 주소를 완성한다.
- 예) import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline.js';
- Editor.builtinPlugins 배열에도 방금 import한 플러그인명을 추가해 준다.
- 소스 수정이 완료되었으면 루트경로로 돌아가서 터미널을 열고 build를 실행한다. (npm run build)
- build가 완료되면 루트경로/build 경로에 빌드된 js 파일이 저장된다.
- 빌드된 js를 적용한 파일에서 에디터를 create할 때도 plugins 배열에 플러그인명을 추가해 준다.
-
ClassicEditor.create(document.querySelector( '#desc' ), { plugins: [ ... "Underline", ... ], ...
-
- 프로젝트를 재 빌드해 결과를 확인해 본다
- 플러그인마다 의존관계인 것들이 있어서 중간중간 missing plugin을 위와 같이 설치했다.
- 툴바 설정도 완료해줬다.. 공식 문서의 도움을 많이 받았다
- 최종적으로 적용한 소스는 다음과 같다.
- HTML
ClassicEditor.create(document.querySelector( '#desc' ), { plugins: [ "Alignment","Bold","Delete","Essentials","FontBackgroundColor", "FontFamily","FontSize","GeneralHtmlSupport","Highlight","HtmlComment", "Image","ImageStyle","ImageToolbar","ImageUpload","ImageResizeEditing","ImageResizeHandles","ImageResize", "Indent","IndentBlock","Input","Italic","Link","LinkImage", "MediaEmbed","MediaEmbedToolbar","Paragraph", "SimpleUploadAdapter","SourceEditing","StandardEditingMode","Strikethrough","Style", "Table","TableCaption","TableColumnResize","TableProperties","TableToolbar", "TextTransformation","Underline" ], toolbar: { items: [ 'bold', 'italic', 'underline', 'strikethrough', '|', 'fontBackgroundColor', 'fontFamily', 'fontSize', '|', 'alignment', 'outdent', 'indent', '|', 'link', 'insertTable', 'imageUpload', 'mediaEmbed', '|', 'undo', 'redo', '|', 'sourceEditing' ] }, simpleUpload: { toolbar: ['imageTextAlternative'], uploadUrl: '/upload', withCredentials: true }, image: { toolbar: [ 'imageTextAlternative', 'linkImage' ] }, fontSize: { options: [ 'default', 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 72 ], supportAllValues: true }, } ) .then( newEditor => { newEditor.ui.getEditableElement().parentElement.insertBefore( newEditor.ui.view.toolbar.element, newEditor.ui.getEditableElement() ); window.ckeditor = newEditor; } ) .catch( error => { console.error( error ); } );
- src/ckeditor.js
/** * @license Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or <https://ckeditor.com/legal/ckeditor-oss-license> */ import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor.js'; import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment.js'; import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat.js'; import AutoLink from '@ckeditor/ckeditor5-link/src/autolink.js'; import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote.js'; import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold.js'; import DataFilter from '@ckeditor/ckeditor5-html-support/src/datafilter.js'; import DataSchema from '@ckeditor/ckeditor5-html-support/src/dataschema.js'; import Delete from '@ckeditor/ckeditor5-typing/src/delete.js'; import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials.js'; import FindAndReplace from '@ckeditor/ckeditor5-find-and-replace/src/findandreplace.js'; import FontBackgroundColor from '@ckeditor/ckeditor5-font/src/fontbackgroundcolor.js'; import FontFamily from '@ckeditor/ckeditor5-font/src/fontfamily.js'; import FontSize from '@ckeditor/ckeditor5-font/src/fontsize.js'; import GeneralHtmlSupport from '@ckeditor/ckeditor5-html-support/src/generalhtmlsupport.js'; import Heading from '@ckeditor/ckeditor5-heading/src/heading.js'; import Highlight from '@ckeditor/ckeditor5-highlight/src/highlight.js'; import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline.js'; import HtmlComment from '@ckeditor/ckeditor5-html-support/src/htmlcomment.js'; import HtmlEmbed from '@ckeditor/ckeditor5-html-embed/src/htmlembed.js'; import Image from '@ckeditor/ckeditor5-image/src/image.js'; import ImageBlockEditing from '@ckeditor/ckeditor5-image/src/image/imageblockediting.js'; import ImageEditing from '@ckeditor/ckeditor5-image/src/image/imageediting.js'; import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload.js'; import ImageUtils from '@ckeditor/ckeditor5-image/src/imageutils.js'; import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize.js'; import ImageResizeEditing from '@ckeditor/ckeditor5-image/src/imageresize/imageresizeediting.js'; import ImageResizeHandles from '@ckeditor/ckeditor5-image/src/imageresize/imageresizehandles.js'; import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle.js'; import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar.js'; import Indent from '@ckeditor/ckeditor5-indent/src/indent.js'; import IndentBlock from '@ckeditor/ckeditor5-indent/src/indentblock.js'; import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic.js'; import Input from '@ckeditor/ckeditor5-typing/src/input.js'; import Link from '@ckeditor/ckeditor5-link/src/link.js'; import LinkEditing from '@ckeditor/ckeditor5-link/src/linkediting.js'; import LinkImage from '@ckeditor/ckeditor5-link/src/linkimage.js'; import LinkImageEditing from '@ckeditor/ckeditor5-link/src/linkimageediting.js'; import LinkUI from '@ckeditor/ckeditor5-link/src/linkui.js'; import List from '@ckeditor/ckeditor5-list/src/list.js'; import ListProperties from '@ckeditor/ckeditor5-list/src/listproperties.js'; import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed.js'; import MediaEmbedToolbar from '@ckeditor/ckeditor5-media-embed/src/mediaembedtoolbar.js'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph.js'; import PasteFromOffice from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice.js'; import SimpleUploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter.js'; import SourceEditing from '@ckeditor/ckeditor5-source-editing/src/sourceediting.js'; import SpecialCharacters from '@ckeditor/ckeditor5-special-characters/src/specialcharacters.js'; import StandardEditingMode from '@ckeditor/ckeditor5-restricted-editing/src/standardeditingmode.js'; import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough.js'; import Style from '@ckeditor/ckeditor5-style/src/style.js'; import Subscript from '@ckeditor/ckeditor5-basic-styles/src/subscript.js'; import Superscript from '@ckeditor/ckeditor5-basic-styles/src/superscript.js'; import Table from '@ckeditor/ckeditor5-table/src/table.js'; import TableCaption from '@ckeditor/ckeditor5-table/src/tablecaption.js'; import TableColumnResize from '@ckeditor/ckeditor5-table/src/tablecolumnresize.js'; import TableProperties from '@ckeditor/ckeditor5-table/src/tableproperties'; import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar.js'; import TextTransformation from '@ckeditor/ckeditor5-typing/src/texttransformation.js'; import Title from '@ckeditor/ckeditor5-heading/src/title.js'; import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline.js'; // plugin 추가 시 본 파일에 import하고 Editor.builtinPlugins에 추가한 후 ckeditor5 폴더에서 npm run build 실행 class Editor extends ClassicEditor {} // Plugins to include in the build. Editor.builtinPlugins = [ Alignment, Autoformat, AutoLink, BlockQuote, Bold, DataFilter, DataSchema, Delete, Essentials, FindAndReplace, FontBackgroundColor, FontFamily, FontSize, GeneralHtmlSupport, Heading, Highlight, HorizontalLine, HtmlComment, HtmlEmbed, Image, ImageBlockEditing, ImageEditing, ImageResize, ImageResizeEditing, ImageResizeHandles, ImageStyle, ImageToolbar, ImageUpload, ImageUtils, Indent, IndentBlock, Input, Italic, Link, LinkEditing, LinkImage, LinkImageEditing, LinkUI, List, ListProperties, MediaEmbed, MediaEmbedToolbar, Paragraph, PasteFromOffice, SimpleUploadAdapter, SourceEditing, SpecialCharacters, StandardEditingMode, Strikethrough, Style, Subscript, Superscript, Table, TableCaption, TableColumnResize, TableProperties, TableToolbar, TextTransformation, Title, Underline ]; // Editor configuration. Editor.defaultConfig = { toolbar: { items: [ 'heading', '|', 'bold', 'italic', 'underline', 'bulletedList', 'numberedList', '|', 'alignment', 'outdent', 'indent', '|', 'imageUpload', 'blockQuote', 'insertTable', 'link', 'mediaEmbed', '|', 'undo', 'redo', '|', 'fontBackgroundColor', 'fontFamily', 'fontSize', '|', 'specialCharacters', 'subscript', 'superscript' ] }, language: 'ko', image: { toolbar: [ // 'toggleImageCaption', // 'imageTextAlternative', 'linkImage' ] }, table: { contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties' ] } }; export default Editor;
npm 사용법과 build된 파일을 사용하는 방식 자체가 익숙하지 않아 어려움이 있었지만
결국 해결 완……..!

CKEditor 4버전
CKEditor 5버전
5버전을 적용해보니 4와 다른 것
- 이미지 업로드 방식이 훨씬 쉬워짐 - 별도 팝업 없이 바로 선택해서 첨부
- table 태그와 img 태그가 그대로 안 들어가고 figure 태그 안에 들어감
- css 수정이 일부 필요했음
- editor 영역이 height가 안 잡혀 있는 듯했음… css를 별도로 추가함
댓글